Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // -*- 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.
- #include <stdio.h>
- #include <stdlib.h>
- //#include <memory.h>
- #include <stdarg.h>
- #include <string.h>
- #include "GBA.h"
- #include "GBAcpu.h"
- #include "GBAinline.h"
- #include "../Globals.h"
- #include "../EEprom.h"
- #include "../Flash.h"
- #include "../Sound.h"
- #include "../Sram.h"
- #include "../bios.h"
- #include "../Cheats.h"
- #include "../NLS.h"
- #include "../elf.h"
- #include "../Util.h"
- #include "../Port.h"
- #include "../System.h"
- #include "agbprint.h"
- #ifdef PROFILING
- #include "prof/prof.h"
- #endif
- #ifdef _MSC_VER
- #define snprintf _snprintf
- #endif
- static int clockTicks;
- static INSN_REGPARM void thumbUnknownInsn(u32 opcode)
- {
- #ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_UNDEFINED)
- log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2);
- #endif
- CPUUndefinedException();
- }
- #ifdef BKPT_SUPPORT
- static INSN_REGPARM void thumbBreakpoint(u32 opcode)
- {
- reg[15].I -= 2;
- armNextPC -= 2;
- dbgSignal(5, opcode & 255);
- clockTicks = -1;
- }
- #endif
- // Common macros //////////////////////////////////////////////////////////
- #ifdef BKPT_SUPPORT
- # define THUMB_CONSOLE_OUTPUT(a,b) do { \
- if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \
- dbgOutput((a), (b)); \
- } \
- } while (0)
- # define UPDATE_OLDREG do { \
- if (debugger_last) { \
- snprintf(oldbuffer, sizeof(oldbuffer), "%08X", \
- armState ? reg[15].I - 4 : reg[15].I - 2); \
- int i; \
- for (i = 0; i < 18; i++) { \
- oldreg[i] = reg[i].I; \
- } \
- } \
- } while (0)
- #else
- # define THUMB_CONSOLE_OUTPUT(a,b)
- # define UPDATE_OLDREG
- #endif
- #define NEG(i) ((i) >> 31)
- #define POS(i) ((~(i)) >> 31)
- #if 1 // Wii port override
- //#ifndef C_CORE
- #ifdef __GNUC__
- #ifdef __POWERPC__
- #define ADD_RD_RS_RN(N) \
- { \
- 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[source].I), \
- "r" (reg[N].I) \
- ); \
- 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 ADD_RD_RS_O3(N) \
- { \
- 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[source].I), \
- "r" (N) \
- ); \
- 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 ADD_RD_RS_O3_0 ADD_RD_RS_O3
- #define ADD_RN_O8(d) \
- {\
- 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[(d)].I), \
- "r" (opcode & 255) \
- ); \
- reg[(d)].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define CMN_RD_RS \
- {\
- 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[dest].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- // Wii port - doesn't compile!
- #define ADC_RD_RS \
- {\
- 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[dest].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 SUB_RD_RS_RN(N) \
- {\
- 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[source].I), \
- "r" (reg[N].I) \
- ); \
- 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 SUB_RD_RS_O3(N) \
- {\
- 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[source].I), \
- "r" (N) \
- ); \
- 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 SUB_RD_RS_O3_0 SUB_RD_RS_O3
- #define SUB_RN_O8(d) \
- {\
- 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[(d)].I), \
- "r" (opcode & 255) \
- ); \
- reg[(d)].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define CMP_RN_O8(d) \
- {\
- 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[(d)].I), \
- "r" (opcode & 255) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- // Wii port - doesn't compile for some reason
- #define SBC_RD_RS \
- {\
- 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[dest].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 NEG_RD_RS \
- {\
- 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[source].I), \
- "r" (0) \
- ); \
- 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 CMP_RD_RS \
- {\
- 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[dest].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #else
- #define EMIT1(op,arg) #op" "arg"; "
- #define EMIT2(op,src,dest) #op" "src", "dest"; "
- #define CONST(val) "$"#val
- #define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
- #define ASMVAR2(prefix,cvar) STRING (prefix) cvar
- #define STRING(x) #x
- #define VAR(var) ASMVAR(#var)
- #define REGREF1(index) ASMVAR("reg("index")")
- #define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
- #define eax "%%eax"
- #define ecx "%%ecx"
- #define edx "%%edx"
- #define ADD_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "addl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=m" (reg[(d)].I));
- #define CMN_RD_RS \
- asm ("add %0, %1;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "r" (value), "r" (reg[dest].I):"1");
- #define ADC_RD_RS \
- asm (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
- "adc %1, %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "r" (value), "b" (reg[dest].I));
- #define SUB_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "subl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=m" (reg[(d)].I));
- #define MOV_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- EMIT2(movb,CONST(0),VAR(N_FLAG)) \
- "movl %%eax, %0;"\
- EMIT1(setzb, VAR(Z_FLAG)) \
- : "=m" (reg[(d)].I));
- #define CMP_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "cmpl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "m" (reg[(d)].I));
- #define SBC_RD_RS \
- asm volatile (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
- "cmc;"\
- "sbb %1, %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "r" (value), "b" (reg[dest].I) : "cc", "memory");
- #define LSL_RD_RS \
- asm ("shl %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define LSR_RD_RS \
- asm ("shr %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define ASR_RD_RS \
- asm ("sar %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define ROR_RD_RS \
- asm ("ror %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define NEG_RD_RS \
- asm ("neg %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "b" (reg[source].I));
- #define CMP_RD_RS \
- asm ("sub %0, %1;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "r" (value), "r" (reg[dest].I):"1");
- #define IMM5_INSN(OP,N) \
- asm("movl %%eax,%%ecx;" \
- "shrl $1,%%eax;" \
- "andl $7,%%ecx;" \
- "andl $0x1C,%%eax;" \
- EMIT2(movl, REGREF1(eax), edx) \
- OP \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, edx, REGREF2(ecx,4)) \
- : : "i" (N))
- #define IMM5_INSN_0(OP) \
- asm("movl %%eax,%%ecx;" \
- "shrl $1,%%eax;" \
- "andl $7,%%ecx;" \
- "andl $0x1C,%%eax;" \
- EMIT2(movl, REGREF1(eax), edx) \
- OP \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, edx, REGREF2(ecx,4)) \
- : : )
- #define IMM5_LSL \
- "shll %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_LSL_0 \
- "testl %%edx,%%edx;"
- #define IMM5_LSR \
- "shrl %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_LSR_0 \
- "testl %%edx,%%edx;"\
- EMIT1(setsb, VAR(C_FLAG)) \
- "xorl %%edx,%%edx;"
- #define IMM5_ASR \
- "sarl %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_ASR_0 \
- "sarl $31,%%edx;"\
- EMIT1(setsb, VAR(C_FLAG))
- #define THREEARG_INSN(OP,N) \
- asm("movl %%eax,%%edx;" \
- "shrl $1,%%edx;" \
- "andl $0x1C,%%edx;" \
- "andl $7,%%eax;" \
- EMIT2(movl, REGREF1(edx), ecx) \
- OP(N) \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, ecx, REGREF2(eax,4)) \
- : : )
- #define ADD_RD_RS_RN(N) \
- EMIT2(add,VAR(reg)"+"#N"*4",ecx) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define ADD_RD_RS_O3(N) \
- "add $"#N",%%ecx;" \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define ADD_RD_RS_O3_0(N) \
- EMIT2(movb,CONST(0),VAR(C_FLAG)) \
- "add $0,%%ecx;" \
- EMIT2(movb,CONST(0),VAR(V_FLAG))
- #define SUB_RD_RS_RN(N) \
- EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define SUB_RD_RS_O3(N) \
- "sub $"#N",%%ecx;" \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define SUB_RD_RS_O3_0(N) \
- EMIT2(movb,CONST(1),VAR(C_FLAG)) \
- "sub $0,%%ecx;" \
- EMIT2(movb,CONST(0),VAR(V_FLAG))
- #endif
- #else // !__GNUC__
- #define ADD_RD_RS_RN(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, dword ptr [OFFSET reg+4*N]\
- __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 ADD_RD_RS_O3(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, N\
- __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 ADD_RD_RS_O3_0 \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, 0\
- __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 mov byte ptr C_FLAG, 0\
- __asm mov byte ptr V_FLAG, 0\
- }
- #define ADD_RN_O8(d) \
- {\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm add dword ptr [OFFSET reg+4*(d)], 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 CMN_RD_RS \
- {\
- __asm mov eax, dest\
- __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 ADC_RD_RS \
- {\
- __asm mov ebx, dest\
- __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 SUB_RD_RS_RN(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, dword ptr [OFFSET reg+4*N]\
- __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 SUB_RD_RS_O3(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, N\
- __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 SUB_RD_RS_O3_0 \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, 0\
- __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 mov byte ptr C_FLAG, 1\
- __asm mov byte ptr V_FLAG, 0\
- }
- #define SUB_RN_O8(d) \
- {\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm sub dword ptr [OFFSET reg + 4*(d)], 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 MOV_RN_O8(d) \
- {\
- __asm mov eax, opcode\
- __asm and eax, 255\
- __asm mov dword ptr [OFFSET reg+4*(d)], eax\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- }
- #define CMP_RN_O8(d) \
- {\
- __asm mov eax, dword ptr [OFFSET reg+4*(d)]\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm sub 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 SBC_RD_RS \
- {\
- __asm mov ebx, dest\
- __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 LSL_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __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_FLAG\
- }
- #define LSL_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr value\
- __asm shl eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define LSR_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __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_FLAG\
- }
- #define LSR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr value\
- __asm shr eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define ASR_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __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_FLAG\
- }
- #define ASR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
- __asm mov cl, byte ptr value\
- __asm sar eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define ROR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
- __asm mov cl, byte ptr value\
- __asm ror eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define NEG_RD_RS \
- {\
- __asm mov ebx, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
- __asm neg ebx\
- __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 CMP_RD_RS \
- {\
- __asm mov eax, dest\
- __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\
- }
- #endif
- #endif
- // C core
- #ifndef ADDCARRY
- #define ADDCARRY(a, b, c) \
- C_FLAG = ((NEG(a) & NEG(b)) |\
- (NEG(a) & POS(c)) |\
- (NEG(b) & POS(c))) ? true : false;
- #endif
- #ifndef ADDOVERFLOW
- #define ADDOVERFLOW(a, b, c) \
- V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
- (POS(a) & POS(b) & NEG(c))) ? true : false;
- #endif
- #ifndef SUBCARRY
- #define SUBCARRY(a, b, c) \
- C_FLAG = ((NEG(a) & POS(b)) |\
- (NEG(a) & POS(c)) |\
- (POS(b) & POS(c))) ? true : false;
- #endif
- #ifndef SUBOVERFLOW
- #define SUBOVERFLOW(a, b, c)\
- V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
- (POS(a) & NEG(b) & NEG(c))) ? true : false;
- #endif
- #ifndef ADD_RD_RS_RN
- #define ADD_RD_RS_RN(N) \
- {\
- u32 lhs = reg[source].I;\
- u32 rhs = reg[N].I;\
- 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);\
- }
- #endif
- #ifndef ADD_RD_RS_O3
- #define ADD_RD_RS_O3(N) \
- {\
- u32 lhs = reg[source].I;\
- u32 rhs = N;\
- 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);\
- }
- #endif
- #ifndef ADD_RD_RS_O3_0
- # define ADD_RD_RS_O3_0 ADD_RD_RS_O3
- #endif
- #ifndef ADD_RN_O8
- #define ADD_RN_O8(d) \
- {\
- u32 lhs = reg[(d)].I;\
- u32 rhs = (opcode & 255);\
- u32 res = lhs + rhs;\
- reg[(d)].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
- #endif
- #ifndef CMN_RD_RS
- #define CMN_RD_RS \
- {\
- u32 lhs = reg[dest].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);\
- }
- #endif
- #ifndef ADC_RD_RS
- #define ADC_RD_RS \
- {\
- u32 lhs = reg[dest].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);\
- }
- #endif
- #ifndef SUB_RD_RS_RN
- #define SUB_RD_RS_RN(N) \
- {\
- u32 lhs = reg[source].I;\
- u32 rhs = reg[N].I;\
- 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);\
- }
- #endif
- #ifndef SUB_RD_RS_O3
- #define SUB_RD_RS_O3(N) \
- {\
- u32 lhs = reg[source].I;\
- u32 rhs = N;\
- 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);\
- }
- #endif
- #ifndef SUB_RD_RS_O3_0
- # define SUB_RD_RS_O3_0 SUB_RD_RS_O3
- #endif
- #ifndef SUB_RN_O8
- #define SUB_RN_O8(d) \
- {\
- u32 lhs = reg[(d)].I;\
- u32 rhs = (opcode & 255);\
- u32 res = lhs - rhs;\
- reg[(d)].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
- #endif
- #ifndef MOV_RN_O8
- #define MOV_RN_O8(d) \
- {\
- reg[d].I = opcode & 255;\
- N_FLAG = false;\
- Z_FLAG = (reg[d].I ? false : true);\
- }
- #endif
- #ifndef CMP_RN_O8
- #define CMP_RN_O8(d) \
- {\
- u32 lhs = reg[(d)].I;\
- u32 rhs = (opcode & 255);\
- u32 res = lhs - rhs;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
- #endif
- #ifndef SBC_RD_RS
- #define SBC_RD_RS \
- {\
- u32 lhs = reg[dest].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);\
- }
- #endif
- #ifndef LSL_RD_RM_I5
- #define LSL_RD_RM_I5 \
- {\
- C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\
- value = reg[source].I << shift;\
- }
- #endif
- #ifndef LSL_RD_RS
- #define LSL_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\
- value = reg[dest].I << value;\
- }
- #endif
- #ifndef LSR_RD_RM_I5
- #define LSR_RD_RM_I5 \
- {\
- C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\
- value = reg[source].I >> shift;\
- }
- #endif
- #ifndef LSR_RD_RS
- #define LSR_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
- value = reg[dest].I >> value;\
- }
- #endif
- #ifndef ASR_RD_RM_I5
- #define ASR_RD_RM_I5 \
- {\
- C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
- value = (s32)reg[source].I >> (int)shift;\
- }
- #endif
- #ifndef ASR_RD_RS
- #define ASR_RD_RS \
- {\
- C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
- value = (s32)reg[dest].I >> (int)value;\
- }
- #endif
- #ifndef ROR_RD_RS
- #define ROR_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
- value = ((reg[dest].I << (32 - value)) |\
- (reg[dest].I >> value));\
- }
- #endif
- #ifndef NEG_RD_RS
- #define NEG_RD_RS \
- {\
- u32 lhs = reg[source].I;\
- u32 rhs = 0;\
- 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);\
- }
- #endif
- #ifndef CMP_RD_RS
- #define CMP_RD_RS \
- {\
- u32 lhs = reg[dest].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);\
- }
- #endif
- #ifndef IMM5_INSN
- #define IMM5_INSN(OP,N) \
- int dest = opcode & 0x07;\
- int source = (opcode >> 3) & 0x07;\
- u32 value;\
- OP(N);\
- reg[dest].I = value;\
- N_FLAG = (value & 0x80000000 ? true : false);\
- Z_FLAG = (value ? false : true);
- #define IMM5_INSN_0(OP) \
- int dest = opcode & 0x07;\
- int source = (opcode >> 3) & 0x07;\
- u32 value;\
- OP;\
- reg[dest].I = value;\
- N_FLAG = (value & 0x80000000 ? true : false);\
- Z_FLAG = (value ? false : true);
- #define IMM5_LSL(N) \
- int shift = N;\
- LSL_RD_RM_I5;
- #define IMM5_LSL_0 \
- value = reg[source].I;
- #define IMM5_LSR(N) \
- int shift = N;\
- LSR_RD_RM_I5;
- #define IMM5_LSR_0 \
- C_FLAG = reg[source].I & 0x80000000 ? true : false;\
- value = 0;
- #define IMM5_ASR(N) \
- int shift = N;\
- ASR_RD_RM_I5;
- #define IMM5_ASR_0 \
- if(reg[source].I & 0x80000000) {\
- value = 0xFFFFFFFF;\
- C_FLAG = true;\
- } else {\
- value = 0;\
- C_FLAG = false;\
- }
- #endif
- #ifndef THREEARG_INSN
- #define THREEARG_INSN(OP,N) \
- int dest = opcode & 0x07; \
- int source = (opcode >> 3) & 0x07; \
- OP(N);
- #endif
- // Shift instructions /////////////////////////////////////////////////////
- #define DEFINE_IMM5_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \
- static INSN_REGPARM void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \
- static INSN_REGPARM void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \
- static INSN_REGPARM void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \
- static INSN_REGPARM void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \
- static INSN_REGPARM void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \
- static INSN_REGPARM void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \
- static INSN_REGPARM void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \
- static INSN_REGPARM void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \
- static INSN_REGPARM void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \
- static INSN_REGPARM void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \
- static INSN_REGPARM void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \
- static INSN_REGPARM void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \
- static INSN_REGPARM void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \
- static INSN_REGPARM void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \
- static INSN_REGPARM void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \
- static INSN_REGPARM void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \
- static INSN_REGPARM void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \
- static INSN_REGPARM void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \
- static INSN_REGPARM void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \
- static INSN_REGPARM void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \
- static INSN_REGPARM void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \
- static INSN_REGPARM void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \
- static INSN_REGPARM void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \
- static INSN_REGPARM void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \
- static INSN_REGPARM void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \
- static INSN_REGPARM void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \
- static INSN_REGPARM void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \
- static INSN_REGPARM void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \
- static INSN_REGPARM void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \
- static INSN_REGPARM void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \
- static INSN_REGPARM void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); }
- // LSL Rd, Rm, #Imm 5
- DEFINE_IMM5_INSN(IMM5_LSL,00)
- // LSR Rd, Rm, #Imm 5
- DEFINE_IMM5_INSN(IMM5_LSR,08)
- // ASR Rd, Rm, #Imm 5
- DEFINE_IMM5_INSN(IMM5_ASR,10)
- // 3-argument ADD/SUB /////////////////////////////////////////////////////
- #define DEFINE_REG3_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \
- static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
- static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
- static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
- static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
- static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
- static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
- static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
- #define DEFINE_IMM3_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \
- static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
- static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
- static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
- static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
- static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
- static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
- static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
- // ADD Rd, Rs, Rn
- DEFINE_REG3_INSN(ADD_RD_RS_RN,18)
- // SUB Rd, Rs, Rn
- DEFINE_REG3_INSN(SUB_RD_RS_RN,1A)
- // ADD Rd, Rs, #Offset3
- DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C)
- // SUB Rd, Rs, #Offset3
- DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E)
- // MOV/CMP/ADD/SUB immediate //////////////////////////////////////////////
- // MOV R0, #Offset8
- static INSN_REGPARM void thumb20(u32 opcode) { MOV_RN_O8(0); }
- // MOV R1, #Offset8
- static INSN_REGPARM void thumb21(u32 opcode) { MOV_RN_O8(1); }
- // MOV R2, #Offset8
- static INSN_REGPARM void thumb22(u32 opcode) { MOV_RN_O8(2); }
- // MOV R3, #Offset8
- static INSN_REGPARM void thumb23(u32 opcode) { MOV_RN_O8(3); }
- // MOV R4, #Offset8
- static INSN_REGPARM void thumb24(u32 opcode) { MOV_RN_O8(4); }
- // MOV R5, #Offset8
- static INSN_REGPARM void thumb25(u32 opcode) { MOV_RN_O8(5); }
- // MOV R6, #Offset8
- static INSN_REGPARM void thumb26(u32 opcode) { MOV_RN_O8(6); }
- // MOV R7, #Offset8
- static INSN_REGPARM void thumb27(u32 opcode) { MOV_RN_O8(7); }
- // CMP R0, #Offset8
- static INSN_REGPARM void thumb28(u32 opcode) { CMP_RN_O8(0); }
- // CMP R1, #Offset8
- static INSN_REGPARM void thumb29(u32 opcode) { CMP_RN_O8(1); }
- // CMP R2, #Offset8
- static INSN_REGPARM void thumb2A(u32 opcode) { CMP_RN_O8(2); }
- // CMP R3, #Offset8
- static INSN_REGPARM void thumb2B(u32 opcode) { CMP_RN_O8(3); }
- // CMP R4, #Offset8
- static INSN_REGPARM void thumb2C(u32 opcode) { CMP_RN_O8(4); }
- // CMP R5, #Offset8
- static INSN_REGPARM void thumb2D(u32 opcode) { CMP_RN_O8(5); }
- // CMP R6, #Offset8
- static INSN_REGPARM void thumb2E(u32 opcode) { CMP_RN_O8(6); }
- // CMP R7, #Offset8
- static INSN_REGPARM void thumb2F(u32 opcode) { CMP_RN_O8(7); }
- // ADD R0,#Offset8
- static INSN_REGPARM void thumb30(u32 opcode) { ADD_RN_O8(0); }
- // ADD R1,#Offset8
- static INSN_REGPARM void thumb31(u32 opcode) { ADD_RN_O8(1); }
- // ADD R2,#Offset8
- static INSN_REGPARM void thumb32(u32 opcode) { ADD_RN_O8(2); }
- // ADD R3,#Offset8
- static INSN_REGPARM void thumb33(u32 opcode) { ADD_RN_O8(3); }
- // ADD R4,#Offset8
- static INSN_REGPARM void thumb34(u32 opcode) { ADD_RN_O8(4); }
- // ADD R5,#Offset8
- static INSN_REGPARM void thumb35(u32 opcode) { ADD_RN_O8(5); }
- // ADD R6,#Offset8
- static INSN_REGPARM void thumb36(u32 opcode) { ADD_RN_O8(6); }
- // ADD R7,#Offset8
- static INSN_REGPARM void thumb37(u32 opcode) { ADD_RN_O8(7); }
- // SUB R0,#Offset8
- static INSN_REGPARM void thumb38(u32 opcode) { SUB_RN_O8(0); }
- // SUB R1,#Offset8
- static INSN_REGPARM void thumb39(u32 opcode) { SUB_RN_O8(1); }
- // SUB R2,#Offset8
- static INSN_REGPARM void thumb3A(u32 opcode) { SUB_RN_O8(2); }
- // SUB R3,#Offset8
- static INSN_REGPARM void thumb3B(u32 opcode) { SUB_RN_O8(3); }
- // SUB R4,#Offset8
- static INSN_REGPARM void thumb3C(u32 opcode) { SUB_RN_O8(4); }
- // SUB R5,#Offset8
- static INSN_REGPARM void thumb3D(u32 opcode) { SUB_RN_O8(5); }
- // SUB R6,#Offset8
- static INSN_REGPARM void thumb3E(u32 opcode) { SUB_RN_O8(6); }
- // SUB R7,#Offset8
- static INSN_REGPARM void thumb3F(u32 opcode) { SUB_RN_O8(7); }
- // ALU operations /////////////////////////////////////////////////////////
- // AND Rd, Rs
- static INSN_REGPARM void thumb40_0(u32 opcode)
- {
- int dest = opcode & 7;
- reg[dest].I &= reg[(opcode >> 3)&7].I;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
- }
- // EOR Rd, Rs
- static INSN_REGPARM void thumb40_1(u32 opcode)
- {
- int dest = opcode & 7;
- reg[dest].I ^= reg[(opcode >> 3)&7].I;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- }
- // LSL Rd, Rs
- static INSN_REGPARM void thumb40_2(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value == 32) {
- value = 0;
- C_FLAG = (reg[dest].I & 1 ? true : false);
- } else if(value < 32) {
- LSL_RD_RS;
- } else {
- value = 0;
- C_FLAG = false;
- }
- reg[dest].I = value;
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
- }
- // LSR Rd, Rs
- static INSN_REGPARM void thumb40_3(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value == 32) {
- value = 0;
- C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
- } else if(value < 32) {
- LSR_RD_RS;
- } else {
- value = 0;
- C_FLAG = false;
- }
- reg[dest].I = value;
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
- }
- // ASR Rd, Rs
- static INSN_REGPARM void thumb41_0(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value < 32) {
- ASR_RD_RS;
- reg[dest].I = value;
- } else {
- if(reg[dest].I & 0x80000000){
- reg[dest].I = 0xFFFFFFFF;
- C_FLAG = true;
- } else {
- reg[dest].I = 0x00000000;
- C_FLAG = false;
- }
- }
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
- }
- // ADC Rd, Rs
- static INSN_REGPARM void thumb41_1(u32 opcode)
- {
- int dest = opcode & 0x07;
- u32 value = reg[(opcode >> 3)&7].I;
- ADC_RD_RS;
- }
- // SBC Rd, Rs
- static INSN_REGPARM void thumb41_2(u32 opcode)
- {
- int dest = opcode & 0x07;
- u32 value = reg[(opcode >> 3)&7].I;
- SBC_RD_RS;
- }
- // ROR Rd, Rs
- static INSN_REGPARM void thumb41_3(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- value = value & 0x1f;
- if(value == 0) {
- C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
- } else {
- ROR_RD_RS;
- reg[dest].I = value;
- }
- }
- clockTicks = codeTicksAccess16(armNextPC)+2;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- }
- // TST Rd, Rs
- static INSN_REGPARM void thumb42_0(u32 opcode)
- {
- u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
- N_FLAG = value & 0x80000000 ? true : false;
- Z_FLAG = value ? false : true;
- }
- // NEG Rd, Rs
- static INSN_REGPARM void thumb42_1(u32 opcode)
- {
- int dest = opcode & 7;
- int source = (opcode >> 3) & 7;
- NEG_RD_RS;
- }
- // CMP Rd, Rs
- static INSN_REGPARM void thumb42_2(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].I;
- CMP_RD_RS;
- }
- // CMN Rd, Rs
- static INSN_REGPARM void thumb42_3(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[(opcode >> 3)&7].I;
- CMN_RD_RS;
- }
- // ORR Rd, Rs
- static INSN_REGPARM void thumb43_0(u32 opcode)
- {
- int dest = opcode & 7;
- reg[dest].I |= reg[(opcode >> 3) & 7].I;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- }
- // MUL Rd, Rs
- static INSN_REGPARM void thumb43_1(u32 opcode)
- {
- clockTicks = 1;
- int dest = opcode & 7;
- u32 rm = reg[dest].I;
- reg[dest].I = reg[(opcode >> 3) & 7].I * rm;
- if (((s32)rm) < 0)
- rm = ~rm;
- if ((rm & 0xFFFFFF00) == 0)
- clockTicks += 0;
- else if ((rm & 0xFFFF0000) == 0)
- clockTicks += 1;
- else if ((rm & 0xFF000000) == 0)
- clockTicks += 2;
- else
- clockTicks += 3;
- busPrefetchCount = (busPrefetchCount<<clockTicks) | (0xFF>>(8-clockTicks));
- clockTicks += codeTicksAccess16(armNextPC) + 1;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- }
- // BIC Rd, Rs
- static INSN_REGPARM void thumb43_2(u32 opcode)
- {
- int dest = opcode & 7;
- reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- }
- // MVN Rd, Rs
- static INSN_REGPARM void thumb43_3(u32 opcode)
- {
- int dest = opcode & 7;
- reg[dest].I = ~reg[(opcode >> 3) & 7].I;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- }
- // High-register instructions and BX //////////////////////////////////////
- // ADD Rd, Hs
- static INSN_REGPARM void thumb44_1(u32 opcode)
- {
- reg[opcode&7].I += reg[((opcode>>3)&7)+8].I;
- }
- // ADD Hd, Rs
- static INSN_REGPARM void thumb44_2(u32 opcode)
- {
- reg[(opcode&7)+8].I += reg[(opcode>>3)&7].I;
- if((opcode&7) == 7) {
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
- }
- // ADD Hd, Hs
- static INSN_REGPARM void thumb44_3(u32 opcode)
- {
- reg[(opcode&7)+8].I += reg[((opcode>>3)&7)+8].I;
- if((opcode&7) == 7) {
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
- }
- // CMP Rd, Hs
- static INSN_REGPARM void thumb45_1(u32 opcode)
- {
- int dest = opcode & 7;
- u32 value = reg[((opcode>>3)&7)+8].I;
- CMP_RD_RS;
- }
- // CMP Hd, Rs
- static INSN_REGPARM void thumb45_2(u32 opcode)
- {
- int dest = (opcode & 7) + 8;
- u32 value = reg[(opcode>>3)&7].I;
- CMP_RD_RS;
- }
- // CMP Hd, Hs
- static INSN_REGPARM void thumb45_3(u32 opcode)
- {
- int dest = (opcode & 7) + 8;
- u32 value = reg[((opcode>>3)&7)+8].I;
- CMP_RD_RS;
- }
- // MOV Rd, Hs
- static INSN_REGPARM void thumb46_1(u32 opcode)
- {
- reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
- }
- // MOV Hd, Rs
- static INSN_REGPARM void thumb46_2(u32 opcode)
- {
- reg[(opcode&7)+8].I = reg[(opcode>>3)&7].I;
- if((opcode&7) == 7) {
- UPDATE_OLDREG;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
- }
- // MOV Hd, Hs
- static INSN_REGPARM void thumb46_3(u32 opcode)
- {
- reg[(opcode&7)+8].I = reg[((opcode>>3)&7)+8].I;
- if((opcode&7) == 7) {
- UPDATE_OLDREG;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
- }
- // BX Rs
- static INSN_REGPARM void thumb47(u32 opcode)
- {
- int base = (opcode >> 3) & 15;
- busPrefetchCount=0;
- UPDATE_OLDREG;
- reg[15].I = reg[base].I;
- if(reg[base].I & 1) {
- armState = false;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)
- + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
- } else {
- armState = true;
- reg[15].I &= 0xFFFFFFFC;
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
- clockTicks = codeTicksAccessSeq32(armNextPC)
- + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
- }
- }
- // Load/store instructions ////////////////////////////////////////////////
- // LDR R0~R7,[PC, #Imm]
- static INSN_REGPARM void thumb48(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[regist].I = CPUReadMemoryQuick(address);
- busPrefetchCount=0;
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
- }
- // STR Rd, [Rs, Rn]
- static INSN_REGPARM void thumb50(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- CPUWriteMemory(address, reg[opcode & 7].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // STRH Rd, [Rs, Rn]
- static INSN_REGPARM void thumb52(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- CPUWriteHalfWord(address, reg[opcode&7].W.W0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // STRB Rd, [Rs, Rn]
- static INSN_REGPARM void thumb54(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I;
- CPUWriteByte(address, reg[opcode & 7].B.B0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // LDSB Rd, [Rs, Rn]
- static INSN_REGPARM void thumb56(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = (s8)CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
- }
- // LDR Rd, [Rs, Rn]
- static INSN_REGPARM void thumb58(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadMemory(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
- }
- // LDRH Rd, [Rs, Rn]
- static INSN_REGPARM void thumb5A(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
- }
- // LDRB Rd, [Rs, Rn]
- static INSN_REGPARM void thumb5C(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
- }
- // LDSH Rd, [Rs, Rn]
- static INSN_REGPARM void thumb5E(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
- }
- // STR Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb60(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
- CPUWriteMemory(address, reg[opcode&7].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // LDR Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb68(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
- reg[opcode&7].I = CPUReadMemory(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
- }
- // STRB Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb70(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
- CPUWriteByte(address, reg[opcode&7].B.B0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // LDRB Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb78(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
- reg[opcode&7].I = CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
- }
- // STRH Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb80(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
- CPUWriteHalfWord(address, reg[opcode&7].W.W0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // LDRH Rd, [Rs, #Imm]
- static INSN_REGPARM void thumb88(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
- reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
- }
- // STR R0~R7, [SP, #Imm]
- static INSN_REGPARM void thumb90(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[regist].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
- }
- // LDR R0~R7, [SP, #Imm]
- static INSN_REGPARM void thumb98(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[regist].I = CPUReadMemoryQuick(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
- }
- // PC/stack-related ///////////////////////////////////////////////////////
- // ADD R0~R7, PC, Imm
- static INSN_REGPARM void thumbA0(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- }
- // ADD R0~R7, SP, Imm
- static INSN_REGPARM void thumbA8(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- reg[regist].I = reg[13].I + ((opcode&255)<<2);
- }
- // ADD SP, Imm
- static INSN_REGPARM void thumbB0(u32 opcode)
- {
- int offset = (opcode & 127) << 2;
- if(opcode & 0x80)
- offset = -offset;
- reg[13].I += offset;
- }
- // Push and pop ///////////////////////////////////////////////////////////
- #define PUSH_REG(val, r) \
- if (opcode & (val)) { \
- CPUWriteMemory(address, reg[(r)].I); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
- #define POP_REG(val, r) \
- if (opcode & (val)) { \
- reg[(r)].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
- // PUSH {Rlist}
- static INSN_REGPARM void thumbB4(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
- u32 address = temp & 0xFFFFFFFC;
- PUSH_REG(1, 0);
- PUSH_REG(2, 1);
- PUSH_REG(4, 2);
- PUSH_REG(8, 3);
- PUSH_REG(16, 4);
- PUSH_REG(32, 5);
- PUSH_REG(64, 6);
- PUSH_REG(128, 7);
- clockTicks += 1 + codeTicksAccess16(armNextPC);
- reg[13].I = temp;
- }
- // PUSH {Rlist, LR}
- static INSN_REGPARM void thumbB5(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
- u32 address = temp & 0xFFFFFFFC;
- PUSH_REG(1, 0);
- PUSH_REG(2, 1);
- PUSH_REG(4, 2);
- PUSH_REG(8, 3);
- PUSH_REG(16, 4);
- PUSH_REG(32, 5);
- PUSH_REG(64, 6);
- PUSH_REG(128, 7);
- PUSH_REG(256, 14);
- clockTicks += 1 + codeTicksAccess16(armNextPC);
- reg[13].I = temp;
- }
- // POP {Rlist}
- static INSN_REGPARM void thumbBC(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- u32 address = reg[13].I & 0xFFFFFFFC;
- u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
- POP_REG(1, 0);
- POP_REG(2, 1);
- POP_REG(4, 2);
- POP_REG(8, 3);
- POP_REG(16, 4);
- POP_REG(32, 5);
- POP_REG(64, 6);
- POP_REG(128, 7);
- reg[13].I = temp;
- clockTicks = 2 + codeTicksAccess16(armNextPC);
- }
- // POP {Rlist, PC}
- static INSN_REGPARM void thumbBD(u32 opcode)
- {
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- u32 address = reg[13].I & 0xFFFFFFFC;
- u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
- POP_REG(1, 0);
- POP_REG(2, 1);
- POP_REG(4, 2);
- POP_REG(8, 3);
- POP_REG(16, 4);
- POP_REG(32, 5);
- POP_REG(64, 6);
- POP_REG(128, 7);
- reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
- if (!count) {
- clockTicks += 1 + dataTicksAccess32(address);
- } else {
- clockTicks += 1 + dataTicksAccessSeq32(address);
- }
- count++;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- reg[13].I = temp;
- THUMB_PREFETCH;
- busPrefetchCount = 0;
- clockTicks += 3 + codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC);
- }
- // Load/store multiple ////////////////////////////////////////////////////
- #define THUMB_STM_REG(val,r,b) \
- if(opcode & (val)) { \
- CPUWriteMemory(address, reg[(r)].I); \
- reg[(b)].I = temp; \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
- #define THUMB_LDM_REG(val,r) \
- if(opcode & (val)) { \
- reg[(r)].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
- // STM R0~7!, {Rlist}
- static INSN_REGPARM void thumbC0(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[regist].I & 0xFFFFFFFC;
- u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
- int count = 0;
- // store
- THUMB_STM_REG(1, 0, regist);
- THUMB_STM_REG(2, 1, regist);
- THUMB_STM_REG(4, 2, regist);
- THUMB_STM_REG(8, 3, regist);
- THUMB_STM_REG(16, 4, regist);
- THUMB_STM_REG(32, 5, regist);
- THUMB_STM_REG(64, 6, regist);
- THUMB_STM_REG(128, 7, regist);
- clockTicks = 1 + codeTicksAccess16(armNextPC);
- }
- // LDM R0~R7!, {Rlist}
- static INSN_REGPARM void thumbC8(u32 opcode)
- {
- u8 regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- u32 address = reg[regist].I & 0xFFFFFFFC;
- u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
- int count = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- clockTicks = 2 + codeTicksAccess16(armNextPC);
- if(!(opcode & (1<<regist)))
- reg[regist].I = temp;
- }
- // Conditional branches ///////////////////////////////////////////////////
- // BEQ offset
- static INSN_REGPARM void thumbD0(u32 opcode)
- {
- UPDATE_OLDREG;
- if(Z_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BNE offset
- static INSN_REGPARM void thumbD1(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!Z_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BCS offset
- static INSN_REGPARM void thumbD2(u32 opcode)
- {
- UPDATE_OLDREG;
- if(C_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BCC offset
- static INSN_REGPARM void thumbD3(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!C_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BMI offset
- static INSN_REGPARM void thumbD4(u32 opcode)
- {
- UPDATE_OLDREG;
- if(N_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BPL offset
- static INSN_REGPARM void thumbD5(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!N_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BVS offset
- static INSN_REGPARM void thumbD6(u32 opcode)
- {
- UPDATE_OLDREG;
- if(V_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BVC offset
- static INSN_REGPARM void thumbD7(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!V_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BHI offset
- static INSN_REGPARM void thumbD8(u32 opcode)
- {
- UPDATE_OLDREG;
- if(C_FLAG && !Z_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BLS offset
- static INSN_REGPARM void thumbD9(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!C_FLAG || Z_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BGE offset
- static INSN_REGPARM void thumbDA(u32 opcode)
- {
- UPDATE_OLDREG;
- if(N_FLAG == V_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BLT offset
- static INSN_REGPARM void thumbDB(u32 opcode)
- {
- UPDATE_OLDREG;
- if(N_FLAG != V_FLAG) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BGT offset
- static INSN_REGPARM void thumbDC(u32 opcode)
- {
- UPDATE_OLDREG;
- if(!Z_FLAG && (N_FLAG == V_FLAG)) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // BLE offset
- static INSN_REGPARM void thumbDD(u32 opcode)
- {
- UPDATE_OLDREG;
- if(Z_FLAG || (N_FLAG != V_FLAG)) {
- reg[15].I += ((s8)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
- codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
- }
- }
- // SWI, B, BL /////////////////////////////////////////////////////////////
- // SWI #comment
- static INSN_REGPARM void thumbDF(u32 opcode)
- {
- u32 address = 0;
- clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) +
- codeTicksAccess16(address)+3;
- busPrefetchCount=0;
- CPUSoftwareInterrupt(opcode & 0xFF);
- }
- // B offset
- static INSN_REGPARM void thumbE0(u32 opcode)
- {
- int offset = (opcode & 0x3FF) << 1;
- if(opcode & 0x0400)
- offset |= 0xFFFFF800;
- reg[15].I += offset;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNex
Add Comment
Please, Sign In to add comment