vbagx/source/vba/arm-new.h
2008-09-15 00:33:15 +00:00

7473 lines
210 KiB
C++

// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef BKPT_SUPPORT
#define CONSOLE_OUTPUT(a,b) \
extern void (*dbgOutput)(char *, u32);\
if((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) {\
dbgOutput((a), (b));\
}
#else
#define CONSOLE_OUTPUT(a,b)
#endif
#define OP_AND \
reg[dest].I = reg[(opcode>>16)&15].I & value;\
CONSOLE_OUTPUT(NULL,reg[2].I);
#define OP_ANDS \
reg[dest].I = reg[(opcode>>16)&15].I & value;\
\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_EOR \
reg[dest].I = reg[(opcode>>16)&15].I ^ value;
#define OP_EORS \
reg[dest].I = reg[(opcode>>16)&15].I ^ value;\
\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#ifdef C_CORE
#define NEG(i) ((i) >> 31)
#define POS(i) ((~(i)) >> 31)
#define ADDCARRY(a, b, c) \
C_FLAG = ((NEG(a) & NEG(b)) |\
(NEG(a) & POS(c)) |\
(NEG(b) & POS(c))) ? true : false;
#define ADDOVERFLOW(a, b, c) \
V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
(POS(a) & POS(b) & NEG(c))) ? true : false;
#define SUBCARRY(a, b, c) \
C_FLAG = ((NEG(a) & POS(b)) |\
(NEG(a) & POS(c)) |\
(POS(b) & POS(c))) ? true : false;
#define SUBOVERFLOW(a, b, c)\
V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
(POS(a) & NEG(b) & NEG(c))) ? true : false;
#define OP_SUB \
{\
reg[dest].I = reg[base].I - value;\
}
#define OP_SUBS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs - rhs;\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(lhs, rhs, res);\
SUBOVERFLOW(lhs, rhs, res);\
}
#define OP_RSB \
{\
reg[dest].I = value - reg[base].I;\
}
#define OP_RSBS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = rhs - lhs;\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(rhs, lhs, res);\
SUBOVERFLOW(rhs, lhs, res);\
}
#define OP_ADD \
{\
reg[dest].I = reg[base].I + value;\
}
#define OP_ADDS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs + rhs;\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
ADDCARRY(lhs, rhs, res);\
ADDOVERFLOW(lhs, rhs, res);\
}
#define OP_ADC \
{\
reg[dest].I = reg[base].I + value + (u32)C_FLAG;\
}
#define OP_ADCS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs + rhs + (u32)C_FLAG;\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
ADDCARRY(lhs, rhs, res);\
ADDOVERFLOW(lhs, rhs, res);\
}
#define OP_SBC \
{\
reg[dest].I = reg[base].I - value - !((u32)C_FLAG);\
}
#define OP_SBCS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs - rhs - !((u32)C_FLAG);\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(lhs, rhs, res);\
SUBOVERFLOW(lhs, rhs, res);\
}
#define OP_RSC \
{\
reg[dest].I = value - reg[base].I - !((u32)C_FLAG);\
}
#define OP_RSCS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = rhs - lhs - !((u32)C_FLAG);\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(rhs, lhs, res);\
SUBOVERFLOW(rhs, lhs, res);\
}
#define OP_CMP \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs - rhs;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(lhs, rhs, res);\
SUBOVERFLOW(lhs, rhs, res);\
}
#define OP_CMN \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs + rhs;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
ADDCARRY(lhs, rhs, res);\
ADDOVERFLOW(lhs, rhs, res);\
}
#define LOGICAL_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
value = v << shift;\
}
#define LOGICAL_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = v >> shift;\
}
#define LOGICAL_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false;\
value = (s32)v >> (int)shift;\
}
#define LOGICAL_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define LOGICAL_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
C_OUT = (v & 1) ? true : false;\
value = ((v >> 1) |\
(shift << 31));\
}
#define LOGICAL_ROR_IMM \
{\
u32 v = opcode & 0xff;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ARITHMETIC_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v << shift;\
}
#define ARITHMETIC_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v >> shift;\
}
#define ARITHMETIC_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = (s32)v >> (int)shift;\
}
#define ARITHMETIC_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ARITHMETIC_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
value = ((v >> 1) |\
(shift << 31));\
}
#define ARITHMETIC_ROR_IMM \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_IMM_MSR \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_VALUE \
{\
value = ((value << (32 - shift)) |\
(value >> shift));\
}
#define RCR_VALUE \
{\
shift = (int)C_FLAG;\
value = ((value >> 1) |\
(shift << 31));\
}
#else
#ifdef __GNUC__
#ifdef __POWERPC__
#define OP_SUB \
{\
reg[dest].I = reg[base].I - value;\
}
#define OP_SUBS \
{\
register int Flags; \
register int Result; \
asm volatile("subco. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_RSB \
{\
reg[dest].I = value - reg[base].I;\
}
#define OP_RSBS \
{\
register int Flags; \
register int Result; \
asm volatile("subfco. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_ADD \
{\
reg[dest].I = reg[base].I + value;\
}
#define OP_ADDS \
{\
register int Flags; \
register int Result; \
asm volatile("addco. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_ADC \
{\
reg[dest].I = reg[base].I + value + (u32)C_FLAG;\
}
#define OP_ADCS \
{\
register int Flags; \
register int Result; \
asm volatile("mtspr xer, %4\n" \
"addeo. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value), \
"r" (C_FLAG << 29) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_SBC \
{\
reg[dest].I = reg[base].I - value - (C_FLAG^1);\
}
#define OP_SBCS \
{\
register int Flags; \
register int Result; \
asm volatile("mtspr xer, %4\n" \
"subfeo. %0, %3, %2\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value), \
"r" (C_FLAG << 29) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_RSC \
{\
reg[dest].I = value - reg[base].I - (C_FLAG^1);\
}
#define OP_RSCS \
{\
register int Flags; \
register int Result; \
asm volatile("mtspr xer, %4\n" \
"subfeo. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value), \
"r" (C_FLAG << 29) \
); \
reg[dest].I = Result; \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_CMP \
{\
register int Flags; \
register int Result; \
asm volatile("subco. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value) \
); \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define OP_CMN \
{\
register int Flags; \
register int Result; \
asm volatile("addco. %0, %2, %3\n" \
"mcrxr cr1\n" \
"mfcr %1\n" \
: "=r" (Result), \
"=r" (Flags) \
: "r" (reg[base].I), \
"r" (value) \
); \
Z_FLAG = (Flags >> 29) & 1; \
N_FLAG = (Flags >> 31) & 1; \
C_FLAG = (Flags >> 25) & 1; \
V_FLAG = (Flags >> 26) & 1; \
}
#define LOGICAL_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
value = v << shift;\
}
#define LOGICAL_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = v >> shift;\
}
#define LOGICAL_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false;\
value = (s32)v >> (int)shift;\
}
#define LOGICAL_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define LOGICAL_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
C_OUT = (v & 1) ? true : false;\
value = ((v >> 1) |\
(shift << 31));\
}
#define LOGICAL_ROR_IMM \
{\
u32 v = opcode & 0xff;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ARITHMETIC_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v << shift;\
}
#define ARITHMETIC_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v >> shift;\
}
#define ARITHMETIC_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = (s32)v >> (int)shift;\
}
#define ARITHMETIC_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ARITHMETIC_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
value = ((v >> 1) |\
(shift << 31));\
}
#define ARITHMETIC_ROR_IMM \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_IMM_MSR \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_VALUE \
{\
value = ((value << (32 - shift)) |\
(value >> shift));\
}
#define RCR_VALUE \
{\
shift = (int)C_FLAG;\
value = ((value >> 1) |\
(shift << 31));\
}
#else
#define OP_SUB \
asm ("sub %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_SUBS \
asm ("sub %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setncb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_RSB \
asm ("sub %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (reg[base].I), "b" (value));
#define OP_RSBS \
asm ("sub %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setncb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (reg[base].I), "b" (value));
#define OP_ADD \
asm ("add %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_ADDS \
asm ("add %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setcb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_ADC \
asm ("bt $0, C_FLAG;"\
"adc %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_ADCS \
asm ("bt $0, C_FLAG;"\
"adc %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setcb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_SBC \
asm ("bt $0, C_FLAG;"\
"cmc;"\
"sbb %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_SBCS \
asm ("bt $0, C_FLAG;"\
"cmc;"\
"sbb %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setncb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (value), "b" (reg[base].I));
#define OP_RSC \
asm ("bt $0, C_FLAG;"\
"cmc;"\
"sbb %1, %%ebx;"\
: "=b" (reg[dest].I)\
: "r" (reg[base].I), "b" (value));
#define OP_RSCS \
asm ("bt $0, C_FLAG;"\
"cmc;"\
"sbb %1, %%ebx;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setncb C_FLAG;"\
"setob V_FLAG;"\
: "=b" (reg[dest].I)\
: "r" (reg[base].I), "b" (value));
#define OP_CMP \
asm ("sub %0, %1;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setncb C_FLAG;"\
"setob V_FLAG;"\
:\
: "r" (value), "r" (reg[base].I));
#define OP_CMN \
asm ("add %0, %1;"\
"setsb N_FLAG;"\
"setzb Z_FLAG;"\
"setcb C_FLAG;"\
"setob V_FLAG;"\
: \
: "r" (value), "r" (reg[base].I));
#define LOGICAL_LSL_REG \
asm("shl %%cl, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define LOGICAL_LSR_REG \
asm("shr %%cl, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define LOGICAL_ASR_REG \
asm("sar %%cl, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define LOGICAL_ROR_REG \
asm("ror %%cl, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define LOGICAL_RRX_REG \
asm("bt $0, C_FLAG;"\
"rcr $1, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (reg[opcode & 0x0f].I));
#define LOGICAL_ROR_IMM \
asm("ror %%cl, %%eax;"\
"setcb %%cl;"\
: "=a" (value), "=c" (C_OUT)\
: "a" (opcode & 0xff), "c" (shift));
#define ARITHMETIC_LSL_REG \
asm("\
shl %%cl, %%eax;"\
: "=a" (value)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define ARITHMETIC_LSR_REG \
asm("\
shr %%cl, %%eax;"\
: "=a" (value)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define ARITHMETIC_ASR_REG \
asm("\
sar %%cl, %%eax;"\
: "=a" (value)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define ARITHMETIC_ROR_REG \
asm("\
ror %%cl, %%eax;"\
: "=a" (value)\
: "a" (reg[opcode & 0x0f].I), "c" (shift));
#define ARITHMETIC_RRX_REG \
asm("\
bt $0, C_FLAG;\
rcr $1, %%eax;"\
: "=a" (value)\
: "a" (reg[opcode & 0x0f].I));
#define ARITHMETIC_ROR_IMM \
asm("\
ror %%cl, %%eax;"\
: "=a" (value)\
: "a" (opcode & 0xff), "c" (shift));
#define ROR_IMM_MSR \
asm ("ror %%cl, %%eax;"\
: "=a" (value)\
: "a" (opcode & 0xFF), "c" (shift));
#define ROR_VALUE \
asm("ror %%cl, %0"\
: "=r" (value)\
: "r" (value), "c" (shift));
#define RCR_VALUE \
asm("bt $0, C_FLAG;"\
"rcr $1, %0"\
: "=r" (value)\
: "r" (value));
#endif
#else
#define OP_SUB \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm sub ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
}
#define OP_SUBS \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm sub ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setnc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_RSB \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm mov eax, value\
__asm sub eax, ebx\
__asm mov ebx, dest\
__asm mov dword ptr [OFFSET reg+4*ebx], eax\
}
#define OP_RSBS \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm mov eax, value\
__asm sub eax, ebx\
__asm mov ebx, dest\
__asm mov dword ptr [OFFSET reg+4*ebx], eax\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setnc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_ADD \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm add ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
}
#define OP_ADDS \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm add ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_ADC \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm bt word ptr C_FLAG, 0\
__asm adc ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
}
#define OP_ADCS \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
__asm bt word ptr C_FLAG, 0\
__asm adc ebx, value\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg+4*eax], ebx\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_SBC \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
__asm mov eax, value\
__asm bt word ptr C_FLAG, 0\
__asm cmc\
__asm sbb ebx, eax\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg + 4*eax], ebx\
}
#define OP_SBCS \
{\
__asm mov ebx, base\
__asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
__asm mov eax, value\
__asm bt word ptr C_FLAG, 0\
__asm cmc\
__asm sbb ebx, eax\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg + 4*eax], ebx\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setnc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_RSC \
{\
__asm mov ebx, value\
__asm mov eax, base\
__asm mov eax, dword ptr[OFFSET reg + 4*eax]\
__asm bt word ptr C_FLAG, 0\
__asm cmc\
__asm sbb ebx, eax\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg + 4*eax], ebx\
}
#define OP_RSCS \
{\
__asm mov ebx, value\
__asm mov eax, base\
__asm mov eax, dword ptr[OFFSET reg + 4*eax]\
__asm bt word ptr C_FLAG, 0\
__asm cmc\
__asm sbb ebx, eax\
__asm mov eax, dest\
__asm mov dword ptr [OFFSET reg + 4*eax], ebx\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setnc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_CMP \
{\
__asm mov eax, base\
__asm mov ebx, dword ptr [OFFSET reg+4*eax]\
__asm sub ebx, value\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setnc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define OP_CMN \
{\
__asm mov eax, base\
__asm mov ebx, dword ptr [OFFSET reg+4*eax]\
__asm add ebx, value\
__asm sets byte ptr N_FLAG\
__asm setz byte ptr Z_FLAG\
__asm setc byte ptr C_FLAG\
__asm seto byte ptr V_FLAG\
}
#define LOGICAL_LSL_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm shl eax, cl\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define LOGICAL_LSR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm shr eax, cl\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define LOGICAL_ASR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm sar eax, cl\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define LOGICAL_ROR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0F\
__asm mov eax, dword ptr [OFFSET reg + 4*eax]\
__asm mov cl, byte ptr shift\
__asm ror eax, cl\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define LOGICAL_RRX_REG \
__asm mov eax, opcode\
__asm and eax, 0x0F\
__asm mov eax, dword ptr [OFFSET reg + 4*eax]\
__asm bt word ptr C_OUT, 0\
__asm rcr eax, 1\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define LOGICAL_ROR_IMM \
__asm mov eax, opcode\
__asm and eax, 0xff\
__asm mov cl, byte ptr shift\
__asm ror eax, cl\
__asm mov value, eax\
__asm setc byte ptr C_OUT
#define ARITHMETIC_LSL_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm shl eax, cl\
__asm mov value, eax
#define ARITHMETIC_LSR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm shr eax, cl\
__asm mov value, eax
#define ARITHMETIC_ASR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0f\
__asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
__asm mov cl, byte ptr shift\
__asm sar eax, cl\
__asm mov value, eax
#define ARITHMETIC_ROR_REG \
__asm mov eax, opcode\
__asm and eax, 0x0F\
__asm mov eax, dword ptr [OFFSET reg + 4*eax]\
__asm mov cl, byte ptr shift\
__asm ror eax, cl\
__asm mov value, eax
#define ARITHMETIC_RRX_REG \
__asm mov eax, opcode\
__asm and eax, 0x0F\
__asm mov eax, dword ptr [OFFSET reg + 4*eax]\
__asm bt word ptr C_FLAG, 0\
__asm rcr eax, 1\
__asm mov value, eax
#define ARITHMETIC_ROR_IMM \
__asm mov eax, opcode\
__asm and eax, 0xff\
__asm mov cl, byte ptr shift\
__asm ror eax, cl\
__asm mov value, eax
#define ROR_IMM_MSR \
{\
__asm mov eax, opcode\
__asm and eax, 0xff\
__asm mov cl, byte ptr shift\
__asm ror eax, CL\
__asm mov value, eax\
}
#define ROR_VALUE \
{\
__asm mov cl, byte ptr shift\
__asm ror dword ptr value, cl\
}
#define RCR_VALUE \
{\
__asm mov cl, byte ptr shift\
__asm bt word ptr C_FLAG, 0\
__asm rcr dword ptr value, 1\
}
#endif
#endif
#define OP_TST \
u32 res = reg[base].I & value;\
N_FLAG = (res & 0x80000000) ? true : false;\
Z_FLAG = (res) ? false : true;\
C_FLAG = C_OUT;
#define OP_TEQ \
u32 res = reg[base].I ^ value;\
N_FLAG = (res & 0x80000000) ? true : false;\
Z_FLAG = (res) ? false : true;\
C_FLAG = C_OUT;
#define OP_ORR \
reg[dest].I = reg[base].I | value;
#define OP_ORRS \
reg[dest].I = reg[base].I | value;\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_MOV \
reg[dest].I = value;
#define OP_MOVS \
reg[dest].I = value;\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_BIC \
reg[dest].I = reg[base].I & (~value);
#define OP_BICS \
reg[dest].I = reg[base].I & (~value);\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_MVN \
reg[dest].I = ~value;
#define OP_MVNS \
reg[dest].I = ~value; \
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define CASE_16(BASE) \
case BASE:\
case BASE+1:\
case BASE+2:\
case BASE+3:\
case BASE+4:\
case BASE+5:\
case BASE+6:\
case BASE+7:\
case BASE+8:\
case BASE+9:\
case BASE+10:\
case BASE+11:\
case BASE+12:\
case BASE+13:\
case BASE+14:\
case BASE+15:
#define CASE_256(BASE) \
CASE_16(BASE)\
CASE_16(BASE+0x10)\
CASE_16(BASE+0x20)\
CASE_16(BASE+0x30)\
CASE_16(BASE+0x40)\
CASE_16(BASE+0x50)\
CASE_16(BASE+0x60)\
CASE_16(BASE+0x70)\
CASE_16(BASE+0x80)\
CASE_16(BASE+0x90)\
CASE_16(BASE+0xa0)\
CASE_16(BASE+0xb0)\
CASE_16(BASE+0xc0)\
CASE_16(BASE+0xd0)\
CASE_16(BASE+0xe0)\
CASE_16(BASE+0xf0)
#define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
case BASE: \
case BASE+8:\
{\
/* OP Rd,Rb,Rm LSL # */ \
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
\
if(shift) {\
LOGICAL_LSL_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+2:\
case BASE+10:\
{\
/* OP Rd,Rb,Rm LSR # */ \
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_LSR_REG\
} else {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
}\
\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+4:\
case BASE+12:\
{\
/* OP Rd,Rb,Rm ASR # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
C_OUT = true;\
} else {\
value = 0;\
C_OUT = false;\
} \
}\
\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+6:\
case BASE+14:\
{\
/* OP Rd,Rb,Rm ROR # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
LOGICAL_RRX_REG\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
} else if(shift < 32) {\
LOGICAL_LSL_REG\
} else {\
value = 0;\
C_OUT = false;\
}\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */ \
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
} else if(shift < 32) {\
LOGICAL_LSR_REG\
} else {\
value = 0;\
C_OUT = false;\
}\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */ \
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift < 32) {\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
C_OUT = true;\
} else {\
value = 0;\
C_OUT = false;\
}\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
C_OUT = (value & 0x80000000 ? true : false);\
}\
} else {\
value = reg[opcode & 0x0F].I;\
C_OUT = (value & 0x80000000 ? true : false);\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+0x200:\
case BASE+0x201:\
case BASE+0x202:\
case BASE+0x203:\
case BASE+0x204:\
case BASE+0x205:\
case BASE+0x206:\
case BASE+0x207:\
case BASE+0x208:\
case BASE+0x209:\
case BASE+0x20a:\
case BASE+0x20b:\
case BASE+0x20c:\
case BASE+0x20d:\
case BASE+0x20e:\
case BASE+0x20f:\
{\
int shift = (opcode & 0xF00) >> 7;\
int base = (opcode >> 16) & 0x0F;\
int dest = (opcode >> 12) & 0x0F;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ROR_IMM\
} else {\
value = opcode & 0xff;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;
#define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \
case BASE: \
case BASE+8:\
{\
/* OP Rd,Rb,Rm LSL # */ \
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
\
if(shift) {\
LOGICAL_LSL_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+2:\
case BASE+10:\
{\
/* OP Rd,Rb,Rm LSR # */ \
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_LSR_REG\
} else {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
}\
\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+4:\
case BASE+12:\
{\
/* OP Rd,Rb,Rm ASR # */\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
C_OUT = true;\
} else {\
value = 0;\
C_OUT = false;\
} \
}\
\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+6:\
case BASE+14:\
{\
/* OP Rd,Rb,Rm ROR # */\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
LOGICAL_RRX_REG\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
clockTicks++;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
} else if(shift < 32) {\
LOGICAL_LSL_REG\
} else {\
value = 0;\
C_OUT = false;\
}\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */ \
clockTicks++;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
} else if(shift < 32) {\
LOGICAL_LSR_REG\
} else {\
value = 0;\
C_OUT = false;\
}\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */ \
clockTicks++;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift < 32) {\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
C_OUT = true;\
} else {\
value = 0;\
C_OUT = false;\
}\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
clockTicks++;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
C_OUT = (value & 0x80000000 ? true : false);\
}\
} else {\
value = reg[opcode & 0x0F].I;\
C_OUT = (value & 0x80000000 ? true : false);\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+0x200:\
case BASE+0x201:\
case BASE+0x202:\
case BASE+0x203:\
case BASE+0x204:\
case BASE+0x205:\
case BASE+0x206:\
case BASE+0x207:\
case BASE+0x208:\
case BASE+0x209:\
case BASE+0x20a:\
case BASE+0x20b:\
case BASE+0x20c:\
case BASE+0x20d:\
case BASE+0x20e:\
case BASE+0x20f:\
{\
int shift = (opcode & 0xF00) >> 7;\
int dest = (opcode >> 12) & 0x0F;\
bool C_OUT = C_FLAG;\
u32 value;\
if(shift) {\
LOGICAL_ROR_IMM\
} else {\
value = opcode & 0xff;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;
#define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
case BASE:\
case BASE+8:\
{\
/* OP Rd,Rb,Rm LSL # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
ARITHMETIC_LSL_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+2:\
case BASE+10:\
{\
/* OP Rd,Rb,Rm LSR # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
ARITHMETIC_LSR_REG\
} else {\
value = 0;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+4:\
case BASE+12:\
{\
/* OP Rd,Rb,Rm ASR # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
ARITHMETIC_ASR_REG\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
} else value = 0;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+6:\
case BASE+14:\
{\
/* OP Rd,Rb,Rm ROR # */\
int base = (opcode >> 16) & 0x0F;\
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
ARITHMETIC_ROR_REG\
} else {\
ARITHMETIC_RRX_REG\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
} else if(shift < 32) {\
ARITHMETIC_LSL_REG\
} else value = 0;\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
if(shift == 32) {\
value = 0;\
} else if(shift < 32) {\
ARITHMETIC_LSR_REG\
} else value = 0;\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift < 32) {\
if(shift) {\
ARITHMETIC_ASR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
} else {\
if(reg[opcode & 0x0F].I & 0x80000000){\
value = 0xFFFFFFFF;\
} else value = 0;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
ARITHMETIC_ROR_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;\
case BASE+0x200:\
case BASE+0x201:\
case BASE+0x202:\
case BASE+0x203:\
case BASE+0x204:\
case BASE+0x205:\
case BASE+0x206:\
case BASE+0x207:\
case BASE+0x208:\
case BASE+0x209:\
case BASE+0x20a:\
case BASE+0x20b:\
case BASE+0x20c:\
case BASE+0x20d:\
case BASE+0x20e:\
case BASE+0x20f:\
{\
int shift = (opcode & 0xF00) >> 7;\
int base = (opcode >> 16) & 0x0F;\
int dest = (opcode >> 12) & 0x0F;\
u32 value;\
{\
ARITHMETIC_ROR_IMM\
}\
if(dest == 15) {\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
}\
} else {\
OPCODE \
}\
}\
break;
u32 opcode = CPUReadMemoryQuick(armNextPC);
clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15];
#ifndef FINAL_VERSION
if(armNextPC == stop)
{
armNextPC++;
}
#endif
armNextPC = reg[15].I;
reg[15].I += 4;
int cond = opcode >> 28;
// suggested optimization for frequent cases
bool cond_res;
if(cond == 0x0e)
{
cond_res = true;
}
else
{
switch(cond)
{
case 0x00: // EQ
cond_res = Z_FLAG;
break;
case 0x01: // NE
cond_res = !Z_FLAG;
break;
case 0x02: // CS
cond_res = C_FLAG;
break;
case 0x03: // CC
cond_res = !C_FLAG;
break;
case 0x04: // MI
cond_res = N_FLAG;
break;
case 0x05: // PL
cond_res = !N_FLAG;
break;
case 0x06: // VS
cond_res = V_FLAG;
break;
case 0x07: // VC
cond_res = !V_FLAG;
break;
case 0x08: // HI
cond_res = C_FLAG && !Z_FLAG;
break;
case 0x09: // LS
cond_res = !C_FLAG || Z_FLAG;
break;
case 0x0A: // GE
cond_res = N_FLAG == V_FLAG;
break;
case 0x0B: // LT
cond_res = N_FLAG != V_FLAG;
break;
case 0x0C: // GT
cond_res = !Z_FLAG &&(N_FLAG == V_FLAG);
break;
case 0x0D: // LE
cond_res = Z_FLAG || (N_FLAG != V_FLAG);
break;
case 0x0E:
cond_res = true;
break;
case 0x0F:
default:
// ???
cond_res = false;
break;
}
}
if(cond_res)
{
switch(((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F))
{
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND, OP_AND, 0x000);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010);
case 0x009:
{
// MUL Rd, Rm, Rs
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs;
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 2;
else if ((rs & 0xFFFF0000) == 0)
clockTicks += 3;
else if ((rs & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
case 0x019:
{
// MULS Rd, Rm, Rs
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs;
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
Z_FLAG = (reg[dest].I) ? false : true;
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 2;
else if ((rs & 0xFFFF0000) == 0)
clockTicks += 3;
else if ((rs & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
case 0x00b:
case 0x02b:
{
// STRH Rd, [Rn], -Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
address -= offset;
reg[base].I = address;
}
break;
case 0x04b:
case 0x06b:
{
// STRH Rd, [Rn], #-offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
address -= offset;
reg[base].I = address;
}
break;
case 0x08b:
case 0x0ab:
{
// STRH Rd, [Rn], Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
address += offset;
reg[base].I = address;
}
break;
case 0x0cb:
case 0x0eb:
{
// STRH Rd, [Rn], #offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
address += offset;
reg[base].I = address;
}
break;
case 0x10b:
{
// STRH Rd, [Rn, -Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x12b:
{
// STRH Rd, [Rn, -Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
break;
case 0x14b:
{
// STRH Rd, [Rn, -#offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x16b:
{
// STRH Rd, [Rn, -#offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
break;
case 0x18b:
{
// STRH Rd, [Rn, Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x1ab:
{
// STRH Rd, [Rn, Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
break;
case 0x1cb:
{
// STRH Rd, [Rn, #offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x1eb:
{
// STRH Rd, [Rn, #offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 4 + CPUUpdateTicksAccess16(address);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
break;
case 0x01b:
case 0x03b:
{
// LDRH Rd, [Rn], -Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x05b:
case 0x07b:
{
// LDRH Rd, [Rn], #-offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x09b:
case 0x0bb:
{
// LDRH Rd, [Rn], Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x0db:
case 0x0fb:
{
// LDRH Rd, [Rn], #offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x11b:
{
// LDRH Rd, [Rn, -Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
}
break;
case 0x13b:
{
// LDRH Rd, [Rn, -Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x15b:
{
// LDRH Rd, [Rn, -#offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
}
break;
case 0x17b:
{
// LDRH Rd, [Rn, -#offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x19b:
{
// LDRH Rd, [Rn, Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
}
break;
case 0x1bb:
{
// LDRH Rd, [Rn, Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x1db:
{
// LDRH Rd, [Rn, #offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
}
break;
case 0x1fb:
{
// LDRH Rd, [Rn, #offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x01d:
case 0x03d:
{
// LDRSB Rd, [Rn], -Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x05d:
case 0x07d:
{
// LDRSB Rd, [Rn], #-offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x09d:
case 0x0bd:
{
// LDRSB Rd, [Rn], Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x0dd:
case 0x0fd:
{
// LDRSB Rd, [Rn], #offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x11d:
{
// LDRSB Rd, [Rn, -Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
}
break;
case 0x13d:
{
// LDRSB Rd, [Rn, -Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x15d:
{
// LDRSB Rd, [Rn, -#offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
}
break;
case 0x17d:
{
// LDRSB Rd, [Rn, -#offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x19d:
{
// LDRSB Rd, [Rn, Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
}
break;
case 0x1bd:
{
// LDRSB Rd, [Rn, Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x1dd:
{
// LDRSB Rd, [Rn, #offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
}
break;
case 0x1fd:
{
// LDRSB Rd, [Rn, #offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x01f:
case 0x03f:
{
// LDRSH Rd, [Rn], -Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x05f:
case 0x07f:
{
// LDRSH Rd, [Rn], #-offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
{
address -= offset;
reg[base].I = address;
}
}
break;
case 0x09f:
case 0x0bf:
{
// LDRSH Rd, [Rn], Rm
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x0df:
case 0x0ff:
{
// LDRSH Rd, [Rn], #offset
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
{
address += offset;
reg[base].I = address;
}
}
break;
case 0x11f:
{
// LDRSH Rd, [Rn, -Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
}
break;
case 0x13f:
{
// LDRSH Rd, [Rn, -Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x15f:
{
// LDRSH Rd, [Rn, -#offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
}
break;
case 0x17f:
{
// LDRSH Rd, [Rn, -#offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x19f:
{
// LDRSH Rd, [Rn, Rm]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
}
break;
case 0x1bf:
{
// LDRSH Rd, [Rn, Rm]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
}
break;
case 0x1df:
{
// LDRSH Rd, [Rn, #offset]
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
}
break;
case 0x1ff:
{
// LDRSH Rd, [Rn, #offset]!
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
}
break;
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030);
case 0x029:
{
// MLA Rd, Rm, Rs, Rn
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I;
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 3;
else if ((rs & 0xFFFF0000) == 0)
clockTicks += 4;
else if ((rs & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
case 0x039:
{
// MLAS Rd, Rm, Rs, Rn
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I;
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
Z_FLAG = (reg[dest].I) ? false : true;
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 3;
else if ((rs & 0xFFFF0000) == 0)
clockTicks += 4;
else if ((rs & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
ARITHMETIC_DATA_OPCODE(OP_SUB, OP_SUB, 0x040);
ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050);
ARITHMETIC_DATA_OPCODE(OP_RSB, OP_RSB, 0x060);
ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070);
ARITHMETIC_DATA_OPCODE(OP_ADD, OP_ADD, 0x080);
ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090);
case 0x089:
{
// UMULL RdLo, RdHi, Rn, Rs
u32 umult = reg[(opcode & 0x0F)].I;
u32 usource = reg[(opcode >> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u64 uTemp = ((u64)umult)*((u64)usource);
reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
if ((usource & 0xFFFFFF00) == 0)
clockTicks += 2;
else if ((usource & 0xFFFF0000) == 0)
clockTicks += 3;
else if ((usource & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
case 0x099:
{
// UMULLS RdLo, RdHi, Rn, Rs
u32 umult = reg[(opcode & 0x0F)].I;
u32 usource = reg[(opcode >> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u64 uTemp = ((u64)umult)*((u64)usource);
reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
Z_FLAG = (uTemp) ? false : true;
N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
if ((usource & 0xFFFFFF00) == 0)
clockTicks += 2;
else if ((usource & 0xFFFF0000) == 0)
clockTicks += 3;
else if ((usource & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
ARITHMETIC_DATA_OPCODE(OP_ADC, OP_ADC, 0x0a0);
ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0);
case 0x0a9:
{
// UMLAL RdLo, RdHi, Rn, Rs
u32 umult = reg[(opcode & 0x0F)].I;
u32 usource = reg[(opcode >> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u64 uTemp = (u64)reg[destHi].I;
uTemp <<= 32;
uTemp |= (u64)reg[destLo].I;
uTemp += ((u64)umult)*((u64)usource);
reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
if ((usource & 0xFFFFFF00) == 0)
clockTicks += 3;
else if ((usource & 0xFFFF0000) == 0)
clockTicks += 4;
else if ((usource & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
case 0x0b9:
{
// UMLALS RdLo, RdHi, Rn, Rs
u32 umult = reg[(opcode & 0x0F)].I;
u32 usource = reg[(opcode >> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u64 uTemp = (u64)reg[destHi].I;
uTemp <<= 32;
uTemp |= (u64)reg[destLo].I;
uTemp += ((u64)umult)*((u64)usource);
reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
Z_FLAG = (uTemp) ? false : true;
N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
if ((usource & 0xFFFFFF00) == 0)
clockTicks += 3;
else if ((usource & 0xFFFF0000) == 0)
clockTicks += 4;
else if ((usource & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
ARITHMETIC_DATA_OPCODE(OP_SBC, OP_SBC, 0x0c0);
ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0);
case 0x0c9:
{
// SMULL RdLo, RdHi, Rm, Rs
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
s64 m = (s32)reg[(opcode & 0x0F)].I;
s64 s = (s32)rs;
s64 sTemp = m*s;
reg[destLo].I = (u32)sTemp;
reg[destHi].I = (u32)(sTemp >> 32);
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 2;
else if((rs & 0xFFFF0000) == 0)
clockTicks += 3;
else if((rs & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
case 0x0d9:
{
// SMULLS RdLo, RdHi, Rm, Rs
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
s64 m = (s32)reg[(opcode & 0x0F)].I;
s64 s = (s32)rs;
s64 sTemp = m*s;
reg[destLo].I = (u32)sTemp;
reg[destHi].I = (u32)(sTemp >> 32);
Z_FLAG = (sTemp) ? false : true;
N_FLAG = (sTemp < 0) ? true : false;
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 2;
else if((rs & 0xFFFF0000) == 0)
clockTicks += 3;
else if((rs & 0xFF000000) == 0)
clockTicks += 4;
else
clockTicks += 5;
}
break;
ARITHMETIC_DATA_OPCODE(OP_RSC, OP_RSC, 0x0e0);
ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0);
case 0x0e9:
{
// SMLAL RdLo, RdHi, Rm, Rs
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
s64 m = (s32)reg[(opcode & 0x0F)].I;
s64 s = (s32)rs;
s64 sTemp = (u64)reg[destHi].I;
sTemp <<= 32;
sTemp |= (u64)reg[destLo].I;
sTemp += m*s;
reg[destLo].I = (u32)sTemp;
reg[destHi].I = (u32)(sTemp >> 32);
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 3;
else if((rs & 0xFFFF0000) == 0)
clockTicks += 4;
else if((rs & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
case 0x0f9:
{
// SMLALS RdLo, RdHi, Rm, Rs
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
s64 m = (s32)reg[(opcode & 0x0F)].I;
s64 s = (s32)rs;
s64 sTemp = (u64)reg[destHi].I;
sTemp <<= 32;
sTemp |= (u64)reg[destLo].I;
sTemp += m*s;
reg[destLo].I = (u32)sTemp;
reg[destHi].I = (u32)(sTemp >> 32);
Z_FLAG = (sTemp) ? false : true;
N_FLAG = (sTemp < 0) ? true : false;
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
clockTicks += 3;
else if((rs & 0xFFFF0000) == 0)
clockTicks += 4;
else if((rs & 0xFF000000) == 0)
clockTicks += 5;
else
clockTicks += 6;
}
break;
LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110);
case 0x100:
// MRS Rd, CPSR
// TODO: check if right instruction....
CPUUpdateCPSR();
reg[(opcode >> 12) & 0x0F].I = reg[16].I;
break;
case 0x109:
{
// SWP Rd, Rm, [Rn]
u32 address = reg[(opcode >> 16) & 15].I;
u32 temp = CPUReadMemory(address);
CPUWriteMemory(address, reg[opcode&15].I);
reg[(opcode >> 12) & 15].I = temp;
}
break;
LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130);
case 0x120:
{
// MSR CPSR_fields, Rm
CPUUpdateCPSR();
u32 value = reg[opcode & 15].I;
u32 newValue = reg[16].I;
if(armMode > 0x10)
{
if(opcode & 0x00010000)
newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
if(opcode & 0x00020000)
newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
if(opcode & 0x00040000)
newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
}
if(opcode & 0x00080000)
newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
newValue |= 0x10;
CPUSwitchMode(newValue & 0x1f, false);
reg[16].I = newValue;
CPUUpdateFlags();
}
break;
case 0x121:
{
// BX Rm
// TODO: check if right instruction...
clockTicks += 3;
int base = opcode & 0x0F;
armState = reg[base].I & 1 ? false : true;
if(armState)
{
reg[15].I = reg[base].I & 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
else
{
reg[15].I = reg[base].I & 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
}
}
break;
ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150);
case 0x140:
// MRS Rd, SPSR
// TODO: check if right instruction...
reg[(opcode >> 12) & 0x0F].I = reg[17].I;
break;
case 0x149:
{
// SWPB Rd, Rm, [Rn]
u32 address = reg[(opcode >> 16) & 15].I;
u32 temp = CPUReadByte(address);
CPUWriteByte(address, reg[opcode&15].B.B0);
reg[(opcode>>12)&15].I = temp;
}
break;
ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170);
case 0x160:
{
// MSR SPSR_fields, Rm
u32 value = reg[opcode & 15].I;
if(armMode > 0x10 && armMode < 0x1f)
{
if(opcode & 0x00010000)
reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
if(opcode & 0x00020000)
reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
if(opcode & 0x00040000)
reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
if(opcode & 0x00080000)
reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
}
}
break;
LOGICAL_DATA_OPCODE (OP_ORR, OP_ORR, 0x180);
LOGICAL_DATA_OPCODE (OP_ORRS, OP_ORR, 0x190);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV, OP_MOV, 0x1a0);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0);
LOGICAL_DATA_OPCODE (OP_BIC, OP_BIC, 0x1c0);
LOGICAL_DATA_OPCODE (OP_BICS, OP_BIC, 0x1d0);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN, OP_MVN, 0x1e0);
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0);
#ifdef BKPT_SUPPORT
case 0x127:
case 0x7ff: // for GDB support
extern void (*dbgSignal)(int,int);
reg[15].I -= 4;
armNextPC -= 4;
dbgSignal(5, (opcode & 0x0f)|((opcode>>4) & 0xfff0));
return;
#endif
case 0x320:
case 0x321:
case 0x322:
case 0x323:
case 0x324:
case 0x325:
case 0x326:
case 0x327:
case 0x328:
case 0x329:
case 0x32a:
case 0x32b:
case 0x32c:
case 0x32d:
case 0x32e:
case 0x32f:
{
// MSR CPSR_fields, #
CPUUpdateCPSR();
u32 value = opcode & 0xFF;
int shift = (opcode & 0xF00) >> 7;
if(shift)
{
ROR_IMM_MSR;
}
u32 newValue = reg[16].I;
if(armMode > 0x10)
{
if(opcode & 0x00010000)
newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
if(opcode & 0x00020000)
newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
if(opcode & 0x00040000)
newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
}
if(opcode & 0x00080000)
newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
newValue |= 0x10;
CPUSwitchMode(newValue & 0x1f, false);
reg[16].I = newValue;
CPUUpdateFlags();
}
break;
case 0x360:
case 0x361:
case 0x362:
case 0x363:
case 0x364:
case 0x365:
case 0x366:
case 0x367:
case 0x368:
case 0x369:
case 0x36a:
case 0x36b:
case 0x36c:
case 0x36d:
case 0x36e:
case 0x36f:
{
// MSR SPSR_fields, #
if(armMode > 0x10 && armMode < 0x1f)
{
u32 value = opcode & 0xFF;
int shift = (opcode & 0xF00) >> 7;
if(shift)
{
ROR_IMM_MSR;
}
if(opcode & 0x00010000)
reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
if(opcode & 0x00020000)
reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
if(opcode & 0x00040000)
reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
if(opcode & 0x00080000)
reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
}
}
break;
CASE_16(0x400)
// T versions shouldn't be different on GBA
CASE_16(0x420)
{
// STR Rd, [Rn], -#
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x480)
// T versions shouldn't be different on GBA
CASE_16(0x4a0)
{
// STR Rd, [Rn], #
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x500)
{
// STR Rd, [Rn, -#]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x520)
{
// STR Rd, [Rn, -#]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x580)
{
// STR Rd, [Rn, #]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x5a0)
{
// STR Rd, [Rn, #]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x410)
{
// LDR Rd, [Rn], -#
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I -= offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x430)
{
// LDRT Rd, [Rn], -#
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I -= offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x490)
{
// LDR Rd, [Rn], #
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I += offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x4b0)
{
// LDRT Rd, [Rn], #
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I += offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
}
break;
CASE_16(0x510)
{
// LDR Rd, [Rn, -#]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x530)
{
// LDR Rd, [Rn, -#]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x590)
{
// LDR Rd, [Rn, #]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x5b0)
{
// LDR Rd, [Rn, #]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x440)
// T versions shouldn't be different on GBA
CASE_16(0x460)
{
// STRB Rd, [Rn], -#
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x4c0)
// T versions shouldn't be different on GBA
CASE_16(0x4e0)
// STRB Rd, [Rn], #
{
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x540)
{
// STRB Rd, [Rn, -#]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x560)
{
// STRB Rd, [Rn, -#]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x5c0)
{
// STRB Rd, [Rn, #]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x5e0)
{
// STRB Rd, [Rn, #]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x450)
// T versions shouldn't be different
CASE_16(0x470)
{
// LDRB Rd, [Rn], -#
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I -= offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x4d0)
CASE_16(0x4f0) // T versions should not be different
{
// LDRB Rd, [Rn], #
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I += offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x550)
{
// LDRB Rd, [Rn, -#]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x570)
{
// LDRB Rd, [Rn, -#]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x5d0)
{
// LDRB Rd, [Rn, #]
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
CASE_16(0x5f0)
{
// LDRB Rd, [Rn, #]!
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x600:
case 0x608:
// T versions are the same
case 0x620:
case 0x628:
{
// STR Rd, [Rn], -Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x602:
case 0x60a:
// T versions are the same
case 0x622:
case 0x62a:
{
// STR Rd, [Rn], -Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x604:
case 0x60c:
// T versions are the same
case 0x624:
case 0x62c:
{
// STR Rd, [Rn], -Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x606:
case 0x60e:
// T versions are the same
case 0x626:
case 0x62e:
{
// STR Rd, [Rn], -Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - value;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x680:
case 0x688:
// T versions are the same
case 0x6a0:
case 0x6a8:
{
// STR Rd, [Rn], Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x682:
case 0x68a:
// T versions are the same
case 0x6a2:
case 0x6aa:
{
// STR Rd, [Rn], Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x684:
case 0x68c:
// T versions are the same
case 0x6a4:
case 0x6ac:
{
// STR Rd, [Rn], Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x686:
case 0x68e:
// T versions are the same
case 0x6a6:
case 0x6ae:
{
// STR Rd, [Rn], Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + value;
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x700:
case 0x708:
{
// STR Rd, [Rn, -Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x702:
case 0x70a:
{
// STR Rd, [Rn, -Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x704:
case 0x70c:
{
// STR Rd, [Rn, -Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x706:
case 0x70e:
{
// STR Rd, [Rn, -Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x720:
case 0x728:
{
// STR Rd, [Rn, -Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x722:
case 0x72a:
{
// STR Rd, [Rn, -Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x724:
case 0x72c:
{
// STR Rd, [Rn, -Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x726:
case 0x72e:
{
// STR Rd, [Rn, -Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x780:
case 0x788:
{
// STR Rd, [Rn, Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x782:
case 0x78a:
{
// STR Rd, [Rn, Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x784:
case 0x78c:
{
// STR Rd, [Rn, Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x786:
case 0x78e:
{
// STR Rd, [Rn, Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x7a0:
case 0x7a8:
{
// STR Rd, [Rn, Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x7a2:
case 0x7aa:
{
// STR Rd, [Rn, Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x7a4:
case 0x7ac:
{
// STR Rd, [Rn, Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x7a6:
case 0x7ae:
{
// STR Rd, [Rn, Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
clockTicks += 2 + CPUUpdateTicksAccess32(address);
}
break;
case 0x610:
case 0x618:
// T versions are the same
case 0x630:
case 0x638:
{
// LDR Rd, [Rn], -Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x612:
case 0x61a:
// T versions are the same
case 0x632:
case 0x63a:
{
// LDR Rd, [Rn], -Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x614:
case 0x61c:
// T versions are the same
case 0x634:
case 0x63c:
{
// LDR Rd, [Rn], -Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x616:
case 0x61e:
// T versions are the same
case 0x636:
case 0x63e:
{
// LDR Rd, [Rn], -Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - value;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x690:
case 0x698:
// T versions are the same
case 0x6b0:
case 0x6b8:
{
// LDR Rd, [Rn], Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x692:
case 0x69a:
// T versions are the same
case 0x6b2:
case 0x6ba:
{
// LDR Rd, [Rn], Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x694:
case 0x69c:
// T versions are the same
case 0x6b4:
case 0x6bc:
{
// LDR Rd, [Rn], Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x696:
case 0x69e:
// T versions are the same
case 0x6b6:
case 0x6be:
{
// LDR Rd, [Rn], Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + value;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x710:
case 0x718:
{
// LDR Rd, [Rn, -Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x712:
case 0x71a:
{
// LDR Rd, [Rn, -Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x714:
case 0x71c:
{
// LDR Rd, [Rn, -Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x716:
case 0x71e:
{
// LDR Rd, [Rn, -Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x730:
case 0x738:
{
// LDR Rd, [Rn, -Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x732:
case 0x73a:
{
// LDR Rd, [Rn, -Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x734:
case 0x73c:
{
// LDR Rd, [Rn, -Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x736:
case 0x73e:
{
// LDR Rd, [Rn, -Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x790:
case 0x798:
{
// LDR Rd, [Rn, Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x792:
case 0x79a:
{
// LDR Rd, [Rn, Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x794:
case 0x79c:
{
// LDR Rd, [Rn, Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x796:
case 0x79e:
{
// LDR Rd, [Rn, Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadMemory(address);
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x7b0:
case 0x7b8:
{
// LDR Rd, [Rn, Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x7b2:
case 0x7ba:
{
// LDR Rd, [Rn, Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x7b4:
case 0x7bc:
{
// LDR Rd, [Rn, Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x7b6:
case 0x7be:
{
// LDR Rd, [Rn, Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess32(address);
if(dest == 15)
{
clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
case 0x640:
case 0x648:
// T versions are the same
case 0x660:
case 0x668:
{
// STRB Rd, [Rn], -Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x642:
case 0x64a:
// T versions are the same
case 0x662:
case 0x66a:
{
// STRB Rd, [Rn], -Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x644:
case 0x64c:
// T versions are the same
case 0x664:
case 0x66c:
{
// STRB Rd, [Rn], -Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x646:
case 0x64e:
// T versions are the same
case 0x666:
case 0x66e:
{
// STRB Rd, [Rn], -Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - value;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6c0:
case 0x6c8:
// T versions are the same
case 0x6e0:
case 0x6e8:
{
// STRB Rd, [Rn], Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6c2:
case 0x6ca:
// T versions are the same
case 0x6e2:
case 0x6ea:
{
// STRB Rd, [Rn], Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6c4:
case 0x6cc:
// T versions are the same
case 0x6e4:
case 0x6ec:
{
// STR Rd, [Rn], Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6c6:
case 0x6ce:
// T versions are the same
case 0x6e6:
case 0x6ee:
{
// STRB Rd, [Rn], Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + value;
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x740:
case 0x748:
{
// STRB Rd, [Rn, -Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x742:
case 0x74a:
{
// STRB Rd, [Rn, -Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x744:
case 0x74c:
{
// STRB Rd, [Rn, -Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x746:
case 0x74e:
{
// STRB Rd, [Rn, -Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x760:
case 0x768:
{
// STRB Rd, [Rn, -Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x762:
case 0x76a:
{
// STRB Rd, [Rn, -Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x764:
case 0x76c:
{
// STRB Rd, [Rn, -Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x766:
case 0x76e:
{
// STRB Rd, [Rn, -Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7c0:
case 0x7c8:
{
// STRB Rd, [Rn, Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7c2:
case 0x7ca:
{
// STRB Rd, [Rn, Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7c4:
case 0x7cc:
{
// STRB Rd, [Rn, Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7c6:
case 0x7ce:
{
// STRB Rd, [Rn, Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7e0:
case 0x7e8:
{
// STRB Rd, [Rn, Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7e2:
case 0x7ea:
{
// STRB Rd, [Rn, Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7e4:
case 0x7ec:
{
// STRB Rd, [Rn, Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7e6:
case 0x7ee:
{
// STRB Rd, [Rn, Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
clockTicks += 2 + CPUUpdateTicksAccess16(address);
}
break;
case 0x650:
case 0x658:
// T versions are the same
case 0x670:
case 0x678:
{
// LDRB Rd, [Rn], -Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x652:
case 0x65a:
// T versions are the same
case 0x672:
case 0x67a:
{
// LDRB Rd, [Rn], -Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x654:
case 0x65c:
// T versions are the same
case 0x674:
case 0x67c:
{
// LDRB Rd, [Rn], -Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x656:
case 0x65e:
// T versions are the same
case 0x676:
case 0x67e:
{
// LDRB Rd, [Rn], -Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - value;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6d0:
case 0x6d8:
// T versions are the same
case 0x6f0:
case 0x6f8:
{
// LDRB Rd, [Rn], Rm, LSL #
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6d2:
case 0x6da:
// T versions are the same
case 0x6f2:
case 0x6fa:
{
// LDRB Rd, [Rn], Rm, LSR #
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6d4:
case 0x6dc:
// T versions are the same
case 0x6f4:
case 0x6fc:
{
// LDRB Rd, [Rn], Rm, ASR #
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x6d6:
case 0x6de:
// T versions are the same
case 0x6f6:
case 0x6fe:
{
// LDRB Rd, [Rn], Rm, ROR #
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + value;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x750:
case 0x758:
{
// LDRB Rd, [Rn, -Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x752:
case 0x75a:
{
// LDRB Rd, [Rn, -Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x754:
case 0x75c:
{
// LDRB Rd, [Rn, -Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x756:
case 0x75e:
{
// LDRB Rd, [Rn, -Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x770:
case 0x778:
{
// LDRB Rd, [Rn, -Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x772:
case 0x77a:
{
// LDRB Rd, [Rn, -Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x774:
case 0x77c:
{
// LDRB Rd, [Rn, -Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x776:
case 0x77e:
{
// LDRB Rd, [Rn, -Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7d0:
case 0x7d8:
{
// LDRB Rd, [Rn, Rm, LSL #]
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7d2:
case 0x7da:
{
// LDRB Rd, [Rn, Rm, LSR #]
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7d4:
case 0x7dc:
{
// LDRB Rd, [Rn, Rm, ASR #]
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7d6:
case 0x7de:
{
// LDRB Rd, [Rn, Rm, ROR #]
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadByte(address);
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7f0:
case 0x7f8:
{
// LDRB Rd, [Rn, Rm, LSL #]!
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7f2:
case 0x7fa:
{
// LDRB Rd, [Rn, Rm, LSR #]!
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7f4:
case 0x7fc:
{
// LDRB Rd, [Rn, Rm, ASR #]!
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
offset = (int)((s32)reg[opcode & 15].I >> shift);
else if(reg[opcode & 15].I & 0x80000000)
offset = 0xFFFFFFFF;
else
offset = 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
case 0x7f6:
case 0x7fe:
{
// LDRB Rd, [Rn, Rm, ROR #]!
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift)
{
ROR_VALUE;
}
else
{
RCR_VALUE;
}
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
clockTicks += 3 + CPUUpdateTicksAccess16(address);
}
break;
#define STMW_REG(val,num) \
if(opcode & (val)) {\
CPUWriteMemory(address, reg[(num)].I);\
if(!offset) {\
reg[base].I = temp;\
clockTicks += 1 + CPUUpdateTicksAccess32(address);\
offset = 1;\
} else {\
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
}\
address += 4;\
}
#define STM_REG(val,num) \
if(opcode & (val)) {\
CPUWriteMemory(address, reg[(num)].I);\
if(!offset) {\
clockTicks += 1 + CPUUpdateTicksAccess32(address);\
offset = 1;\
} else {\
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
}\
address += 4;\
}
CASE_16(0x800)
// STMDA Rn, {Rlist}
{
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
STM_REG(8192, 13);
STM_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x820)
{
// STMDA Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
STMW_REG(8192, 13);
STMW_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
reg[base].I = temp;
}
}
break;
CASE_16(0x840)
{
// STMDA Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
if(armMode == 0x11)
{
STM_REG(256, R8_FIQ);
STM_REG(512, R9_FIQ);
STM_REG(1024, R10_FIQ);
STM_REG(2048, R11_FIQ);
STM_REG(4096, R12_FIQ);
}
else
{
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STM_REG(8192, R13_USR);
STM_REG(16384, R14_USR);
}
else
{
STM_REG(8192, 13);
STM_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x860)
{
// STMDA Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
if(armMode == 0x11)
{
STMW_REG(256, R8_FIQ);
STMW_REG(512, R9_FIQ);
STMW_REG(1024, R10_FIQ);
STMW_REG(2048, R11_FIQ);
STMW_REG(4096, R12_FIQ);
}
else
{
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STMW_REG(8192, R13_USR);
STMW_REG(16384, R14_USR);
}
else
{
STMW_REG(8192, 13);
STMW_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
reg[base].I = temp;
}
}
break;
CASE_16(0x880)
{
// STMIA Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
STM_REG(8192, 13);
STM_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x8a0)
{
// STMIA Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
STMW_REG(8192, 13);
STMW_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
{
reg[base].I = temp;
clockTicks += 1 + CPUUpdateTicksAccess32(address);
}
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x8c0)
{
// STMIA Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
if(armMode == 0x11)
{
STM_REG(256, R8_FIQ);
STM_REG(512, R9_FIQ);
STM_REG(1024, R10_FIQ);
STM_REG(2048, R11_FIQ);
STM_REG(4096, R12_FIQ);
}
else
{
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STM_REG(8192, R13_USR);
STM_REG(16384, R14_USR);
}
else
{
STM_REG(8192, 13);
STM_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x8e0)
{
// STMIA Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
if(armMode == 0x11)
{
STMW_REG(256, R8_FIQ);
STMW_REG(512, R9_FIQ);
STMW_REG(1024, R10_FIQ);
STMW_REG(2048, R11_FIQ);
STMW_REG(4096, R12_FIQ);
}
else
{
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STMW_REG(8192, R13_USR);
STMW_REG(16384, R14_USR);
}
else
{
STMW_REG(8192, 13);
STMW_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
{
reg[base].I = temp;
clockTicks += 1 + CPUUpdateTicksAccess32(address);
}
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x900)
{
// STMDB Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
STM_REG(8192, 13);
STM_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x920)
{
// STMDB Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
STMW_REG(8192, 13);
STMW_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
reg[base].I = temp;
}
}
break;
CASE_16(0x940)
{
// STMDB Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
if(armMode == 0x11)
{
STM_REG(256, R8_FIQ);
STM_REG(512, R9_FIQ);
STM_REG(1024, R10_FIQ);
STM_REG(2048, R11_FIQ);
STM_REG(4096, R12_FIQ);
}
else
{
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STM_REG(8192, R13_USR);
STM_REG(16384, R14_USR);
}
else
{
STM_REG(8192, 13);
STM_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x960)
{
// STMDB Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
if(armMode == 0x11)
{
STMW_REG(256, R8_FIQ);
STMW_REG(512, R9_FIQ);
STMW_REG(1024, R10_FIQ);
STMW_REG(2048, R11_FIQ);
STMW_REG(4096, R12_FIQ);
}
else
{
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STMW_REG(8192, R13_USR);
STMW_REG(16384, R14_USR);
}
else
{
STMW_REG(8192, 13);
STMW_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
reg[base].I = temp;
}
}
break;
CASE_16(0x980)
// STMIB Rn, {Rlist}
{
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
STM_REG(8192, 13);
STM_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x9a0)
{
// STMIB Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
STMW_REG(8192, 13);
STMW_REG(16384, 14);
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
{
reg[base].I = temp;
clockTicks += 1 + CPUUpdateTicksAccess32(address);
}
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x9c0)
{
// STMIB Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
STM_REG(4, 2);
STM_REG(8, 3);
STM_REG(16, 4);
STM_REG(32, 5);
STM_REG(64, 6);
STM_REG(128, 7);
if(armMode == 0x11)
{
STM_REG(256, R8_FIQ);
STM_REG(512, R9_FIQ);
STM_REG(1024, R10_FIQ);
STM_REG(2048, R11_FIQ);
STM_REG(4096, R12_FIQ);
}
else
{
STM_REG(256, 8);
STM_REG(512, 9);
STM_REG(1024, 10);
STM_REG(2048, 11);
STM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STM_REG(8192, R13_USR);
STM_REG(16384, R14_USR);
}
else
{
STM_REG(8192, 13);
STM_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
clockTicks += 1 + CPUUpdateTicksAccess32(address);
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
CASE_16(0x9e0)
{
// STMIB Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
STMW_REG(1, 0);
STMW_REG(2, 1);
STMW_REG(4, 2);
STMW_REG(8, 3);
STMW_REG(16, 4);
STMW_REG(32, 5);
STMW_REG(64, 6);
STMW_REG(128, 7);
if(armMode == 0x11)
{
STMW_REG(256, R8_FIQ);
STMW_REG(512, R9_FIQ);
STMW_REG(1024, R10_FIQ);
STMW_REG(2048, R11_FIQ);
STMW_REG(4096, R12_FIQ);
}
else
{
STMW_REG(256, 8);
STMW_REG(512, 9);
STMW_REG(1024, 10);
STMW_REG(2048, 11);
STMW_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
STMW_REG(8192, R13_USR);
STMW_REG(16384, R14_USR);
}
else
{
STMW_REG(8192, 13);
STMW_REG(16384, 14);
}
if(opcode & 32768)
{
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
{
reg[base].I = temp;
clockTicks += 1 + CPUUpdateTicksAccess32(address);
}
else
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
}
}
break;
#define LDM_REG(val,num) \
if(opcode & (val)) {\
reg[(num)].I = CPUReadMemory(address);\
if(offset)\
clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
else {\
clockTicks += 1 + CPUUpdateTicksAccess32(address);\
offset = 1;\
}\
address += 4;\
}
CASE_16(0x810)
{
// LDMDA Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x830)
{
// LDMDA Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
break;
CASE_16(0x850)
{
// LDMDA Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
}
}
break;
CASE_16(0x870)
{
// LDMDA Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if(!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
}
break;
CASE_16(0x890)
{
// LDMIA Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x8b0)
{
// LDMIA Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
break;
CASE_16(0x8d0)
{
// LDMIA Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
}
}
break;
CASE_16(0x8f0)
{
// LDMIA Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = reg[base].I & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if(!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
}
break;
CASE_16(0x910)
{
// LDMDB Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x930)
{
// LDMDB Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
break;
CASE_16(0x950)
{
// LDMDB Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
}
}
break;
CASE_16(0x970)
{
// LDMDB Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if(!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
}
break;
CASE_16(0x990)
{
// LDMIB Rn, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
}
break;
CASE_16(0x9b0)
{
// LDMIB Rn!, {Rlist}
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
if(opcode & 32768)
{
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
break;
CASE_16(0x9d0)
{
// LDMIB Rn, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if (!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
}
}
break;
CASE_16(0x9f0)
{
// LDMIB Rn!, {Rlist}^
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
clockTicks += 2;
int offset = 0;
if(opcode & 0x8000)
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
LDM_REG(8192, 13);
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
if(!offset)
clockTicks += 2 + CPUUpdateTicksAccess32(address);
else
clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState)
{
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
}
else
{
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
}
}
else
{
LDM_REG(1, 0);
LDM_REG(2, 1);
LDM_REG(4, 2);
LDM_REG(8, 3);
LDM_REG(16, 4);
LDM_REG(32, 5);
LDM_REG(64, 6);
LDM_REG(128, 7);
if(armMode == 0x11)
{
LDM_REG(256, R8_FIQ);
LDM_REG(512, R9_FIQ);
LDM_REG(1024, R10_FIQ);
LDM_REG(2048, R11_FIQ);
LDM_REG(4096, R12_FIQ);
}
else
{
LDM_REG(256, 8);
LDM_REG(512, 9);
LDM_REG(1024, 10);
LDM_REG(2048, 11);
LDM_REG(4096, 12);
}
if(armMode != 0x10 && armMode != 0x1f)
{
LDM_REG(8192, R13_USR);
LDM_REG(16384, R14_USR);
}
else
{
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
}
break;
CASE_256(0xa00)
{
// B <offset>
clockTicks += 3;
int offset = opcode & 0x00FFFFFF;
if(offset & 0x00800000)
{
offset |= 0xFF000000;
}
offset <<= 2;
reg[15].I += offset;
armNextPC = reg[15].I;
reg[15].I += 4;
}
break;
CASE_256(0xb00)
{
// BL <offset>
clockTicks += 3;
int offset = opcode & 0x00FFFFFF;
if(offset & 0x00800000)
{
offset |= 0xFF000000;
}
offset <<= 2;
reg[14].I = reg[15].I - 4;
reg[15].I += offset;
armNextPC = reg[15].I;
reg[15].I += 4;
}
break;
CASE_256(0xf00)
// SWI <comment>
clockTicks += 3;
CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
break;
#ifdef GP_SUPPORT
case 0xe11:
case 0xe13:
case 0xe15:
case 0xe17:
case 0xe19:
case 0xe1b:
case 0xe1d:
case 0xe1f:
// MRC
break;
case 0xe01:
case 0xe03:
case 0xe05:
case 0xe07:
case 0xe09:
case 0xe0b:
case 0xe0d:
case 0xe0f:
// MRC
break;
#endif
default:
#ifdef DEV_VERSION
if(systemVerbose & VERBOSE_UNDEFINED)
log("Undefined ARM instruction %08x at %08x\n", opcode,
armNextPC-4);
#endif
CPUUndefinedException();
break;
// END
}
}