/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2012 DeSmuME team
This file 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 of the License, or
(at your option) any later version.
This file 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 the this software. If not, see .
*/
// ARM core TODO:
// - Check all the LDM/STM opcodes: quirks when Rb included in Rlist; opcodes
// operating on user registers (LDMXX2/STMXX2)
// - Force User mode memory access for LDRx/STRx opcodes with bit24=0 and bit21=1
// (has to be done at memory side; once the PU is emulated well enough)
// - Check LDMxx2/STMxx2 (those opcodes that act on User mode registers instead
// of current ones)
#include "cp15.h"
#include "MMU.h"
#include "armcpu.h"
#include "NDSSystem.h"
#include "MMU_timing.h"
#define cpu (&ARMPROC)
#define TEMPLATE template
// -----------------------------------------------------------------------------
// Shifting macros
// -----------------------------------------------------------------------------
#define LSL_IMM \
uint32_t shift_op = cpu->R[REG_POS(i, 0)] << ((i >> 7) & 0x1F);
#define S_LSL_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], 32 - shift_op); \
shift_op = cpu->R[REG_POS(i, 0)] << shift_op; \
}
#define LSL_REG \
uint32_t shift_op = cpu->R[REG_POS(i, 8)] & 0xFF; \
if (shift_op >= 32) \
shift_op = 0; \
else \
shift_op = cpu->R[REG_POS(i, 0)] << shift_op;
#define S_LSL_REG \
uint32_t shift_op = cpu->R[REG_POS(i,8)] & 0xFF; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else if (shift_op < 32) \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], 32 - shift_op); \
shift_op = cpu->R[REG_POS(i, 0)] << shift_op; \
} \
else if (shift_op == 32) \
{ \
shift_op = 0; \
c = BIT0(cpu->R[REG_POS(i, 0)]); \
} \
else \
{ \
shift_op = 0; \
c = 0; \
}
#define LSR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
if (shift_op) \
shift_op = cpu->R[REG_POS(i, 0)] >> shift_op;
#define S_LSR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
c = BIT31(cpu->R[REG_POS(i, 0)]); \
else \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = cpu->R[REG_POS(i, 0)]>>shift_op; \
}
#define LSR_REG \
uint32_t shift_op = cpu->R[REG_POS(i,8)] & 0xFF; \
if (shift_op >= 32) \
shift_op = 0; \
else \
shift_op = cpu->R[REG_POS(i, 0)] >> shift_op;
#define S_LSR_REG \
uint32_t shift_op = cpu->R[REG_POS(i,8)] & 0xFF; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i ,0)]; \
else if (shift_op < 32) \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = cpu->R[REG_POS(i, 0)] >> shift_op; \
} \
else if (shift_op == 32) \
{ \
c = BIT31(cpu->R[REG_POS(i, 0)]); \
shift_op = 0; \
} \
else \
{ \
c = 0; \
shift_op = 0; \
}
#define ASR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
if (!shift_op) \
shift_op = BIT31(cpu->R[REG_POS(i, 0)]) * 0xFFFFFFFF; \
else \
shift_op = static_cast(static_cast(cpu->R[REG_POS(i, 0)]) >> shift_op);
#define S_ASR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
{ \
shift_op = BIT31(cpu->R[REG_POS(i, 0)]) * 0xFFFFFFFF; \
c = BIT31(cpu->R[REG_POS(i, 0)]); \
} \
else \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = static_cast(static_cast(cpu->R[REG_POS(i, 0)]) >> shift_op); \
}
#define ASR_REG \
uint32_t shift_op = cpu->R[REG_POS(i,8)] & 0xFF; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else if (shift_op < 32) \
shift_op = static_cast(static_cast(cpu->R[REG_POS(i, 0)]) >> shift_op); \
else \
shift_op = BIT31(cpu->R[REG_POS(i, 0)]) * 0xFFFFFFFF;
#define S_ASR_REG \
uint32_t shift_op = cpu->R[REG_POS(i, 8)] & 0xFF; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else if (shift_op < 32) \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = static_cast(static_cast(cpu->R[REG_POS(i, 0)]) >> shift_op); \
} \
else \
{ \
c = BIT31(cpu->R[REG_POS(i, 0)]); \
shift_op = BIT31(cpu->R[REG_POS(i, 0)]) * 0xFFFFFFFF; \
}
#define ROR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
if (!shift_op) \
shift_op = (static_cast(cpu->CPSR.bits.C) << 31) | (cpu->R[REG_POS(i, 0)] >> 1); \
else \
shift_op = ROR(cpu->R[REG_POS(i, 0)], shift_op);
#define S_ROR_IMM \
uint32_t shift_op = (i >> 7) & 0x1F; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
{ \
shift_op = (static_cast(cpu->CPSR.bits.C) << 31) | (cpu->R[REG_POS(i, 0)] >> 1); \
c = BIT0(cpu->R[REG_POS(i, 0)]); \
} \
else \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = ROR(cpu->R[REG_POS(i, 0)], shift_op); \
}
#define ROR_REG \
uint32_t shift_op = cpu->R[REG_POS(i, 8)] & 0xFF; \
if (!shift_op || !(shift_op & 0x1F)) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else \
shift_op = ROR(cpu->R[REG_POS(i, 0)], shift_op & 0x1F);
#define S_ROR_REG \
uint32_t shift_op = cpu->R[REG_POS(i, 8)] & 0xFF; \
uint32_t c = cpu->CPSR.bits.C; \
if (!shift_op) \
shift_op = cpu->R[REG_POS(i, 0)]; \
else \
{ \
shift_op &= 0x1F; \
if (!shift_op) \
{ \
shift_op = cpu->R[REG_POS(i, 0)]; \
c = BIT31(cpu->R[REG_POS(i, 0)]); \
} \
else \
{ \
c = BIT_N(cpu->R[REG_POS(i, 0)], shift_op - 1); \
shift_op = ROR(cpu->R[REG_POS(i, 0)], shift_op); \
} \
}
#define IMM_VALUE \
uint32_t shift_op = ROR(i & 0xFF, (i >> 7) & 0x1E);
#define S_IMM_VALUE \
uint32_t shift_op = ROR(i & 0xFF, (i >> 7) & 0x1E); \
uint32_t c = cpu->CPSR.bits.C; \
if ((i >> 8) & 0xF) \
c = BIT31(shift_op);
#define IMM_OFF (((i >> 4) & 0xF0) + (i & 0xF))
#define IMM_OFF_12 ((i) & 0xFFF)
// -----------------------------------------------------------------------------
// Undefined instruction
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_UND(uint32_t)
{
TRAPUNDEF(cpu);
return 1;
}
// -----------------------------------------------------------------------------
// AND / ANDS
// Timing: OK
// -----------------------------------------------------------------------------
#define OP_AND(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] & shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_ANDS(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] & shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a;
TEMPLATE static uint32_t FASTCALL OP_AND_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_AND(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_LSL_REG(uint32_t i)
{
LSL_REG;
OP_AND(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_AND(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_LSR_REG(uint32_t i)
{
LSR_REG;
OP_AND(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_AND(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_ASR_REG(uint32_t i)
{
ASR_REG;
OP_AND(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_AND(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_ROR_REG(uint32_t i)
{
ROR_REG;
OP_AND(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_AND(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_ANDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_ANDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_ANDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_ANDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_ANDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_ANDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_ANDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_ANDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_AND_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_ANDS(1, 3);
}
// -----------------------------------------------------------------------------
// EOR / EORS
// -----------------------------------------------------------------------------
#define OP_EOR(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] ^ shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_EORS(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] ^ shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a;
TEMPLATE static uint32_t FASTCALL OP_EOR_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_EOR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_LSL_REG(uint32_t i)
{
LSL_REG;
OP_EOR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_EOR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_LSR_REG(uint32_t i)
{
LSR_REG;
OP_EOR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_EOR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_ASR_REG(uint32_t i)
{
ASR_REG;
OP_EOR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_EOR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_ROR_REG(uint32_t i)
{
ROR_REG;
OP_EOR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_EOR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_EORS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_EORS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_EORS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_EORS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_EORS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_EORS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_EORS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_EORS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_EOR_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_EORS(1, 3);
}
// -----------------------------------------------------------------------------
// SUB / SUBS
// -----------------------------------------------------------------------------
#define OP_SUB(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] - shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_SUBS(a, b) \
cpu->R[REG_POS(i, 12)] = v - shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.C = !BorrowFrom(v, shift_op); \
cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i,12)], v, shift_op); \
return a;
TEMPLATE static uint32_t FASTCALL OP_SUB_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_SUB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_LSL_REG(uint32_t i)
{
LSL_REG;
OP_SUB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_SUB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_LSR_REG(uint32_t i)
{
LSR_REG;
OP_SUB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_SUB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_ASR_REG(uint32_t i)
{
ASR_REG;
OP_SUB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_SUB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_ROR_REG(uint32_t i)
{
ROR_REG;
OP_SUB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_SUB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_SUBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_SUBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_IMM;
OP_SUBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_SUBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_SUBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_REG;
OP_SUBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_IMM;
OP_SUBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_SUBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SUB_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
IMM_VALUE;
OP_SUBS(1, 3);
}
// -----------------------------------------------------------------------------
// RSB / RSBS
// -----------------------------------------------------------------------------
#define OP_RSB(a, b) \
cpu->R[REG_POS(i, 12)] = shift_op - cpu->R[REG_POS(i, 16)]; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_RSBS(a, b) \
cpu->R[REG_POS(i, 12)] = shift_op - v; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.C = !BorrowFrom(shift_op, v); \
cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i, 12)], shift_op, v); \
return a;
TEMPLATE static uint32_t FASTCALL OP_RSB_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_RSB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_LSL_REG(uint32_t i)
{
LSL_REG;
OP_RSB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_RSB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_LSR_REG(uint32_t i)
{
LSR_REG;
OP_RSB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_RSB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_ASR_REG(uint32_t i)
{
ASR_REG;
OP_RSB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_RSB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_ROR_REG(uint32_t i)
{
ROR_REG;
OP_RSB(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_RSB(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_RSBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_RSBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_IMM;
OP_RSBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_RSBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_RSBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_REG;
OP_RSBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_IMM;
OP_RSBS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_RSBS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSB_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
IMM_VALUE;
OP_RSBS(1, 3);
}
// -----------------------------------------------------------------------------
// ADD / ADDS
// -----------------------------------------------------------------------------
#define OP_ADD(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] + shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_ADDS(a, b) \
cpu->R[REG_POS(i,12)] = v + shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.C = CarryFrom(v, shift_op); \
cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_POS(i, 12)], v, shift_op); \
return a;
TEMPLATE static uint32_t FASTCALL OP_ADD_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_ADD(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_LSL_REG(uint32_t i)
{
LSL_REG;
OP_ADD(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_ADD(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_LSR_REG(uint32_t i)
{
LSR_REG;
OP_ADD(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_ADD(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_ASR_REG(uint32_t i)
{
ASR_REG;
OP_ADD(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_ADD(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_ROR_REG(uint32_t i)
{
ROR_REG;
OP_ADD(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_ADD(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_ADDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_ADDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_IMM;
OP_ADDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_ADDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_ADDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_REG;
OP_ADDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_IMM;
OP_ADDS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_ADDS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADD_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
IMM_VALUE;
OP_ADDS(1, 3);
}
// -----------------------------------------------------------------------------
// ADC / ADCS
// -----------------------------------------------------------------------------
#define OP_ADC(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] + shift_op + cpu->CPSR.bits.C; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_ADCS(a, b) \
{ \
if (REG_POS(i, 12) == 15) \
{ \
cpu->R[REG_POS(i, 12)] = v + shift_op + cpu->CPSR.bits.C; \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
if (!cpu->CPSR.bits.C) \
{ \
cpu->R[REG_POS(i, 12)] = v + shift_op; \
cpu->CPSR.bits.C = cpu->R[REG_POS(i, 12)] < v; \
} \
else \
{ \
cpu->R[REG_POS(i, 12)] = v + shift_op + 1; \
cpu->CPSR.bits.C = cpu->R[REG_POS(i, 12)] <= v; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.V = BIT31((v ^ shift_op ^ -1) & (v ^ cpu->R[REG_POS(i, 12)])); \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_ADC_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_ADC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_LSL_REG(uint32_t i)
{
LSL_REG;
OP_ADC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_ADC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_LSR_REG(uint32_t i)
{
LSR_REG;
OP_ADC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_ADC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_ASR_REG(uint32_t i)
{
ASR_REG;
OP_ADC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_ADC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_ROR_REG(uint32_t i)
{
ROR_REG;
OP_ADC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_ADC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_ADCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_ADCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_IMM;
OP_ADCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_ADCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_ADCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i,16)];
ASR_REG;
OP_ADCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_IMM;
OP_ADCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_ADCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ADC_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i,16)];
IMM_VALUE;
OP_ADCS(1, 3);
}
// -----------------------------------------------------------------------------
// SBC / SBCS
// -----------------------------------------------------------------------------
#define OP_SBC(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] - shift_op - !cpu->CPSR.bits.C; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_SBCS(a, b) \
{ \
if (REG_POS(i, 12) == 15) \
{ \
cpu->R[REG_POS(i,12)] = v - shift_op - !cpu->CPSR.bits.C; \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
if (!cpu->CPSR.bits.C) \
{ \
cpu->R[REG_POS(i, 12)] = v - shift_op - 1; \
cpu->CPSR.bits.C = v > shift_op; \
} \
else \
{ \
cpu->R[REG_POS(i, 12)] = v - shift_op; \
cpu->CPSR.bits.C = v >= shift_op; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.V = BIT31((v ^ shift_op) & (v ^ cpu->R[REG_POS(i, 12)])); \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_SBC_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_SBC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_LSL_REG(uint32_t i)
{
LSL_REG;
OP_SBC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_SBC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_LSR_REG(uint32_t i)
{
LSR_REG;
OP_SBC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_SBC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_ASR_REG(uint32_t i)
{
ASR_REG;
OP_SBC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_SBC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_ROR_REG(uint32_t i)
{
ROR_REG;
OP_SBC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_SBC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_SBCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_SBCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_IMM;
OP_SBCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_SBCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_SBCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_REG;
OP_SBCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i,16)];
ROR_IMM;
OP_SBCS(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_SBCS(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_SBC_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
IMM_VALUE;
OP_SBCS(1, 3);
}
// -----------------------------------------------------------------------------
// RSC / RSCS
// -----------------------------------------------------------------------------
#define OP_RSC(a, b) \
cpu->R[REG_POS(i, 12)] = shift_op - cpu->R[REG_POS(i, 16)] + cpu->CPSR.bits.C - 1; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_RSCS(a, b) \
{ \
if (REG_POS(i, 12) == 15) \
{ \
cpu->R[REG_POS(i, 12)] = shift_op - v - !cpu->CPSR.bits.C; \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
if (!cpu->CPSR.bits.C) \
{ \
cpu->R[REG_POS(i, 12)] = shift_op - v - 1; \
cpu->CPSR.bits.C = shift_op > v; \
} \
else \
{ \
cpu->R[REG_POS(i, 12)] = shift_op - v; \
cpu->CPSR.bits.C = shift_op >= v; \
} \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
cpu->CPSR.bits.V = BIT31((shift_op ^ v) & (shift_op ^ cpu->R[REG_POS(i, 12)])); \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_RSC_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_RSC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_LSL_REG(uint32_t i)
{
LSL_REG;
OP_RSC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_RSC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_LSR_REG(uint32_t i)
{
LSR_REG;
OP_RSC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_RSC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_ASR_REG(uint32_t i)
{
ASR_REG;
OP_RSC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_RSC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_ROR_REG(uint32_t i)
{
ROR_REG;
OP_RSC(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_RSC(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_LSL_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_IMM;
OP_RSCS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_LSL_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSL_REG;
OP_RSCS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_LSR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i,16)];
LSR_IMM;
OP_RSCS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_LSR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
LSR_REG;
OP_RSCS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_ASR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_IMM;
OP_RSCS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_ASR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ASR_REG;
OP_RSCS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_ROR_IMM(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_IMM;
OP_RSCS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_ROR_REG(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
ROR_REG;
OP_RSCS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_RSC_S_IMM_VAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 16)];
IMM_VALUE;
OP_RSCS(1,3);
}
// -----------------------------------------------------------------------------
// TST
// -----------------------------------------------------------------------------
#define OP_TST(a) \
{ \
uint32_t tmp = cpu->R[REG_POS(i, 16)] & shift_op; \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(tmp); \
cpu->CPSR.bits.Z = !tmp; \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_TST_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_TST(1);
}
TEMPLATE static uint32_t FASTCALL OP_TST_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_TST(2);
}
TEMPLATE static uint32_t FASTCALL OP_TST_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_TST(1);
}
TEMPLATE static uint32_t FASTCALL OP_TST_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_TST(2);
}
TEMPLATE static uint32_t FASTCALL OP_TST_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_TST(1);
}
TEMPLATE static uint32_t FASTCALL OP_TST_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_TST(2);
}
TEMPLATE static uint32_t FASTCALL OP_TST_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_TST(1);
}
TEMPLATE static uint32_t FASTCALL OP_TST_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_TST(2);
}
TEMPLATE static uint32_t FASTCALL OP_TST_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_TST(1);
}
// -----------------------------------------------------------------------------
// TEQ
// -----------------------------------------------------------------------------
#define OP_TEQ(a) \
{ \
unsigned tmp = cpu->R[REG_POS(i, 16)] ^ shift_op; \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(tmp); \
cpu->CPSR.bits.Z = !tmp; \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_TEQ(1);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_TEQ(2);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_TEQ(1);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_TEQ(2);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_TEQ(1);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_TEQ(2);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_TEQ(1);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_TEQ(2);
}
TEMPLATE static uint32_t FASTCALL OP_TEQ_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_TEQ(1);
}
// -----------------------------------------------------------------------------
// CMP
// -----------------------------------------------------------------------------
#define OP_CMP(a) \
{ \
uint32_t tmp = cpu->R[REG_POS(i, 16)] - shift_op; \
cpu->CPSR.bits.N = BIT31(tmp); \
cpu->CPSR.bits.Z = !tmp; \
cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_POS(i, 16)], shift_op); \
cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_POS(i, 16)], shift_op); \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_CMP_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_CMP(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_LSL_REG(uint32_t i)
{
LSL_REG;
OP_CMP(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_CMP(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_LSR_REG(uint32_t i)
{
LSR_REG;
OP_CMP(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_CMP(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_ASR_REG(uint32_t i)
{
ASR_REG;
OP_CMP(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_CMP(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_ROR_REG(uint32_t i)
{
ROR_REG;
OP_CMP(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMP_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_CMP(1);
}
// -----------------------------------------------------------------------------
// CMN
// -----------------------------------------------------------------------------
#define OP_CMN(a) \
{ \
uint32_t tmp = cpu->R[REG_POS(i, 16)] + shift_op; \
cpu->CPSR.bits.N = BIT31(tmp); \
cpu->CPSR.bits.Z = !tmp; \
cpu->CPSR.bits.C = CarryFrom(cpu->R[REG_POS(i, 16)], shift_op); \
cpu->CPSR.bits.V = OverflowFromADD(tmp, cpu->R[REG_POS(i, 16)], shift_op); \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_CMN_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_CMN(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_LSL_REG(uint32_t i)
{
LSL_REG;
OP_CMN(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_CMN(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_LSR_REG(uint32_t i)
{
LSR_REG;
OP_CMN(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_CMN(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_ASR_REG(uint32_t i)
{
ASR_REG;
OP_CMN(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_CMN(1);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_ROR_REG(uint32_t i)
{
ROR_REG;
OP_CMN(2);
}
TEMPLATE static uint32_t FASTCALL OP_CMN_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_CMN(1);
}
// -----------------------------------------------------------------------------
// ORR / ORRS
// -----------------------------------------------------------------------------
#define OP_ORR(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] | shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_ORRS(a,b) \
{ \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] | shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a; \
}
TEMPLATE static uint32_t FASTCALL OP_ORR_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_ORR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_LSL_REG(uint32_t i)
{
LSL_REG;
OP_ORR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_ORR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_LSR_REG(uint32_t i)
{
LSR_REG;
OP_ORR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_ORR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_ASR_REG(uint32_t i)
{
ASR_REG;
OP_ORR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_ORR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_ROR_REG(uint32_t i)
{
ROR_REG;
OP_ORR(2, 4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_ORR(1, 3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_ORRS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_ORRS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_ORRS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_ORRS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_ORRS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_ORRS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_ORRS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_ORRS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_ORR_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_ORRS(1,3);
}
// -----------------------------------------------------------------------------
// MOV / MOVS
// -----------------------------------------------------------------------------
#define OP_MOV(a, b) \
cpu->R[REG_POS(i, 12)] = shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = shift_op; \
return b; \
} \
return a;
#define OP_MOVS(a, b) \
cpu->R[REG_POS(i, 12)] = shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a;
TEMPLATE static uint32_t FASTCALL OP_MOV_LSL_IMM(uint32_t i)
{
if (i == 0xE1A00000) // nop: MOV R0, R0
return 1;
LSL_IMM;
OP_MOV(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_LSL_REG(uint32_t i)
{
LSL_REG;
if (REG_POS(i, 0) == 15)
shift_op += 4;
OP_MOV(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_MOV(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_LSR_REG(uint32_t i)
{
LSR_REG;
if (REG_POS(i, 0) == 15)
shift_op += 4;
OP_MOV(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_MOV(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_ASR_REG(uint32_t i)
{
ASR_REG;
OP_MOV(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_MOV(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_ROR_REG(uint32_t i)
{
ROR_REG;
OP_MOV(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_MOV(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_MOVS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
if (REG_POS(i, 0) == 15)
shift_op += 4;
OP_MOVS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_MOVS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
if (REG_POS(i, 0) == 15)
shift_op += 4;
OP_MOVS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_MOVS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_MOVS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_MOVS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_MOVS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MOV_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_MOVS(1,3);
}
// -----------------------------------------------------------------------------
// BIC / BICS
// -----------------------------------------------------------------------------
#define OP_BIC(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] & ~shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_BICS(a, b) \
cpu->R[REG_POS(i, 12)] = cpu->R[REG_POS(i, 16)] & ~shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a;
TEMPLATE static uint32_t FASTCALL OP_BIC_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_BIC(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_LSL_REG(uint32_t i)
{
LSL_REG;
OP_BIC(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_BIC(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_LSR_REG(uint32_t i)
{
LSR_REG;
OP_BIC(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_BIC(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_ASR_REG(uint32_t i)
{
ASR_REG;
OP_BIC(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_BIC(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_ROR_REG(uint32_t i)
{
ROR_REG;
OP_BIC(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_BIC(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_BICS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_BICS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_BICS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_BICS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_BICS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_BICS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_BICS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_BICS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_BIC_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_BICS(1,3);
}
// -----------------------------------------------------------------------------
// MVN / MVNS
// -----------------------------------------------------------------------------
#define OP_MVN(a, b) \
cpu->R[REG_POS(i, 12)] = ~shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
return a;
#define OP_MVNS(a, b) \
cpu->R[REG_POS(i, 12)] = ~shift_op; \
if (REG_POS(i, 12) == 15) \
{ \
Status_Reg SPSR = cpu->SPSR; \
armcpu_switchMode(cpu, SPSR.bits.mode); \
cpu->CPSR = SPSR; \
cpu->changeCPSR(); \
cpu->R[15] &= 0xFFFFFFFC | (static_cast(cpu->CPSR.bits.T) << 1); \
cpu->next_instruction = cpu->R[15]; \
return b; \
} \
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 12)]); \
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 12)]; \
return a;
TEMPLATE static uint32_t FASTCALL OP_MVN_LSL_IMM(uint32_t i)
{
LSL_IMM;
OP_MVN(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_LSL_REG(uint32_t i)
{
LSL_REG;
OP_MVN(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_LSR_IMM(uint32_t i)
{
LSR_IMM;
OP_MVN(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_LSR_REG(uint32_t i)
{
LSR_REG;
OP_MVN(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_ASR_IMM(uint32_t i)
{
ASR_IMM;
OP_MVN(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_ASR_REG(uint32_t i)
{
ASR_REG;
OP_MVN(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_ROR_IMM(uint32_t i)
{
ROR_IMM;
OP_MVN(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_ROR_REG(uint32_t i)
{
ROR_REG;
OP_MVN(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_IMM_VAL(uint32_t i)
{
IMM_VALUE;
OP_MVN(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSL_IMM(uint32_t i)
{
S_LSL_IMM;
OP_MVNS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSL_REG(uint32_t i)
{
S_LSL_REG;
OP_MVNS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSR_IMM(uint32_t i)
{
S_LSR_IMM;
OP_MVNS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSR_REG(uint32_t i)
{
S_LSR_REG;
OP_MVNS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_ASR_IMM(uint32_t i)
{
S_ASR_IMM;
OP_MVNS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_ASR_REG(uint32_t i)
{
S_ASR_REG;
OP_MVNS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_ROR_IMM(uint32_t i)
{
S_ROR_IMM;
OP_MVNS(1,3);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_ROR_REG(uint32_t i)
{
S_ROR_REG;
OP_MVNS(2,4);
}
TEMPLATE static uint32_t FASTCALL OP_MVN_S_IMM_VAL(uint32_t i)
{
S_IMM_VALUE;
OP_MVNS(1,3);
}
// -----------------------------------------------------------------------------
// MUL / MULS / MLA / MLAS
// -----------------------------------------------------------------------------
#define MUL_Mxx_END(c) \
v >>= 8; \
if (!v || v == 0xFFFFFF) \
return c + 1; \
v >>= 8; \
if (!v || v == 0xFFFF) \
return c + 2; \
v >>= 8; \
if (!v || v == 0xFF) \
return c + 3; \
return c + 4;
TEMPLATE static uint32_t FASTCALL OP_MUL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
cpu->R[REG_POS(i, 16)] = cpu->R[REG_POS(i, 0)] * v;
MUL_Mxx_END(1);
}
TEMPLATE static uint32_t FASTCALL OP_MLA(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
cpu->R[REG_POS(i, 16)] = cpu->R[REG_POS(i, 0)] * v + cpu->R[REG_POS(i, 12)];
MUL_Mxx_END(2);
}
TEMPLATE static uint32_t FASTCALL OP_MUL_S(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
cpu->R[REG_POS(i, 16)] = cpu->R[REG_POS(i, 0)] * v;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)];
MUL_Mxx_END(1);
}
TEMPLATE static uint32_t FASTCALL OP_MLA_S(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
cpu->R[REG_POS(i, 16)] = cpu->R[REG_POS(i, 0)] * v + cpu->R[REG_POS(i, 12)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)];
MUL_Mxx_END(2);
}
// -----------------------------------------------------------------------------
// UMULL / UMULLS / UMLAL / UMLALS
// -----------------------------------------------------------------------------
#define MUL_UMxxL_END(c) \
v >>= 8; \
if (!v) \
return c + 1; \
v >>= 8; \
if (!v) \
return c + 2; \
v >>= 8; \
if (!v) \
return c + 3; \
return c + 4;
TEMPLATE static uint32_t FASTCALL OP_UMULL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
uint64_t res = static_cast(cpu->R[REG_POS(i, 0)]) * static_cast(v);
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32);
MUL_UMxxL_END(2);
}
TEMPLATE static uint32_t FASTCALL OP_UMLAL(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
uint64_t res = static_cast(cpu->R[REG_POS(i, 0)]) * static_cast(v);
// RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */
// RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo)
uint32_t tmp = static_cast(res); // low
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32) + cpu->R[REG_POS(i, 16)] + CarryFrom(tmp, cpu->R[REG_POS(i, 12)]);
cpu->R[REG_POS(i, 12)] += tmp;
MUL_UMxxL_END(3);
}
TEMPLATE static uint32_t FASTCALL OP_UMULL_S(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
uint64_t res = static_cast(cpu->R[REG_POS(i, 0)]) * static_cast(v);
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)] && !cpu->R[REG_POS(i, 12)];
MUL_UMxxL_END(2);
}
TEMPLATE static uint32_t FASTCALL OP_UMLAL_S(uint32_t i)
{
uint32_t v = cpu->R[REG_POS(i, 8)];
uint64_t res = static_cast(cpu->R[REG_POS(i, 0)]) * static_cast(v);
// RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */
// RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo)
uint32_t tmp = static_cast(res); // low
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32) + cpu->R[REG_POS(i, 16)] + CarryFrom(tmp, cpu->R[REG_POS(i, 12)]);
cpu->R[REG_POS(i, 12)] += tmp;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)] & !cpu->R[REG_POS(i, 12)];
MUL_UMxxL_END(3);
}
// -----------------------------------------------------------------------------
// SMULL / SMULLS / SMLAL / SMLALS
// -----------------------------------------------------------------------------
#define MUL_SMxxL_END(c) \
v &= 0xFFFFFFFF; \
v >>= 8; \
if (!v || v == 0xFFFFFF) \
return c + 1; \
v >>= 8; \
if (!v || v == 0xFFFF) \
return c + 2; \
v >>= 8; \
if (!v || v == 0xFF) \
return c + 3; \
return c + 4;
TEMPLATE static uint32_t FASTCALL OP_SMULL(uint32_t i)
{
int64_t v = static_cast(cpu->R[REG_POS(i, 8)]);
int64_t res = v * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32);
MUL_SMxxL_END(2);
}
TEMPLATE static uint32_t FASTCALL OP_SMLAL(uint32_t i)
{
int64_t v = static_cast(cpu->R[REG_POS(i, 8)]);
int64_t res = v * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
uint32_t tmp = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32) + cpu->R[REG_POS(i, 16)] + CarryFrom(tmp, cpu->R[REG_POS(i, 12)]);
cpu->R[REG_POS(i, 12)] += tmp;
MUL_SMxxL_END(3);
}
TEMPLATE static uint32_t FASTCALL OP_SMULL_S(uint32_t i)
{
int64_t v = static_cast(cpu->R[REG_POS(i, 8)]);
int64_t res = v * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)] & !cpu->R[REG_POS(i, 12)];
MUL_SMxxL_END(2);
}
TEMPLATE static uint32_t FASTCALL OP_SMLAL_S(uint32_t i)
{
int64_t v = static_cast(cpu->R[REG_POS(i, 8)]);
int64_t res = v * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
uint32_t tmp = static_cast(res);
cpu->R[REG_POS(i, 16)] = static_cast(res >> 32) + cpu->R[REG_POS(i, 16)] + CarryFrom(tmp, cpu->R[REG_POS(i, 12)]);
cpu->R[REG_POS(i, 12)] += tmp;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i, 16)]);
cpu->CPSR.bits.Z = !cpu->R[REG_POS(i, 16)] & !cpu->R[REG_POS(i, 12)];
MUL_SMxxL_END(3);
}
// -----------------------------------------------------------------------------
// SWP / SWPB
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_SWP(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
uint32_t tmp = ROR(READ32(cpu->mem_if->data, adr), (adr & 3) << 3);
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i, 0)]);
cpu->R[REG_POS(i, 12)] = tmp;
uint32_t c = MMU_memAccessCycles(adr);
c += MMU_memAccessCycles(adr);
return MMU_aluMemCycles(4, c);
}
TEMPLATE static uint32_t FASTCALL OP_SWPB(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
uint8_t tmp = READ8(cpu->mem_if->data, adr);
WRITE8(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 0)] & 0xFF));
cpu->R[REG_POS(i, 12)] = tmp;
uint32_t c = MMU_memAccessCycles(adr);
c += MMU_memAccessCycles(adr);
return MMU_aluMemCycles(4, c);
}
// -----------------------------------------------------------------------------
// LDRH
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_LDRH_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(READ16(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
// -----------------------------------------------------------------------------
// STRH
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_STRH_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
cpu->R[REG_POS(i, 16)] += IMM_OFF;
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_POS_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
cpu->R[REG_POS(i, 16)] -= IMM_OFF;
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_POS_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
cpu->R[REG_POS(i, 16)] += cpu->R[REG_POS(i, 0)];
return MMU_aluMemAccessCycles(2, adr);
}
TEMPLATE static uint32_t FASTCALL OP_STRH_POS_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
WRITE16(cpu->mem_if->data, adr, static_cast(cpu->R[REG_POS(i, 12)]));
cpu->R[REG_POS(i, 16)] -= cpu->R[REG_POS(i, 0)];
return MMU_aluMemAccessCycles(2, adr);
}
// -----------------------------------------------------------------------------
// LDRSH
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_LDRSH_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ16(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
// -----------------------------------------------------------------------------
// LDRSB
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_LDRSB_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF;
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 16)] = adr;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= IMM_OFF;
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] += cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 16)] -= cpu->R[REG_POS(i, 0)];
cpu->R[REG_POS(i, 12)] = static_cast(static_cast(READ8(cpu->mem_if->data, adr)));
return MMU_aluMemAccessCycles(3, adr);
}
// -----------------------------------------------------------------------------
// MRS / MSR
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_MRS_CPSR(uint32_t i)
{
cpu->R[REG_POS(i, 12)] = cpu->CPSR.val;
return 1;
}
TEMPLATE static uint32_t FASTCALL OP_MRS_SPSR(uint32_t i)
{
cpu->R[REG_POS(i, 12)] = cpu->SPSR.val;
return 1;
}
#define OP_MSR_CPSR_(operand) \
uint32_t byte_mask = cpu->CPSR.bits.mode == USR ? (BIT19(i) ? 0xFF000000 : 0x00000000) : \
(BIT16(i) ? 0x000000FF : 0x00000000) | (BIT17(i) ? 0x0000FF00:0x00000000) | (BIT18(i) ? 0x00FF0000 : 0x00000000) | (BIT19(i) ? 0xFF000000 : 0x00000000); \
if (cpu->CPSR.bits.mode != USR && BIT16(i)) \
armcpu_switchMode(cpu, operand & 0x1F); \
cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); \
cpu->changeCPSR();
#define OP_MSR_SPSR_(operand) \
if (cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) \
return 1; \
uint32_t byte_mask = (BIT16(i) ? 0x000000FF : 0x00000000) | (BIT17(i) ? 0x0000FF00 : 0x00000000) | (BIT18(i) ? 0x00FF0000 : 0x00000000) | (BIT19(i) ? 0xFF000000 : 0x00000000); \
cpu->SPSR.val = (cpu->SPSR.val & ~byte_mask) | (operand & byte_mask); \
cpu->changeCPSR();
//#define __NEW_MSR
#ifdef __NEW_MSR
#define v4T_UNALLOC_MASK 0x0FFFFF00
#define v4T_USER_MASK 0xF0000000
#define v4T_PRIV_MASK 0x0000000F
#define v4T_STATE_MASK 0x00000020
#define v5TE_UNALLOC_MASK 0x07FFFF00
#define v5TE_USER_MASK 0xF8000000
#define v5TE_PRIV_MASK 0x0000000F
#define v5TE_STATE_MASK 0x00000020
#endif
TEMPLATE static uint32_t FASTCALL OP_MSR_CPSR(uint32_t i)
{
uint32_t operand = cpu->R[REG_POS(i, 0)];
#ifdef __NEW_MSR
uint32_t mask = 0;
uint32_t byte_mask = (BIT16(i) ? 0x000000FF : 0x00000000) | (BIT17(i) ? 0x0000FF00 : 0x00000000) | (BIT18(i) ? 0x00FF0000 : 0x00000000) | (BIT19(i) ? 0xFF000000 : 0x00000000);
uint32_t unallocMask = PROCNUM?v4T_UNALLOC_MASK : v5TE_UNALLOC_MASK;
uint32_t userMask = PROCNUM?v4T_USER_MASK : v5TE_USER_MASK;
uint32_t privMask = PROCNUM?v4T_PRIV_MASK : v5TE_PRIV_MASK;
uint32_t stateMask = PROCNUM?v4T_STATE_MASK : v5TE_STATE_MASK;
if (operand & unallocMask)
fprintf(stderr, "ARM%c: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", PROCNUM ? '7' : '9', operand);
if (cpu->CPSR.bits.mode != USR) // Privileged mode
{
if (BIT16(i))
armcpu_switchMode(cpu, operand & 0x1F);
if (operand & stateMask)
fprintf(stderr, "ARM%c: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", PROCNUM ? '7' : '9', operand);
else
mask = byte_mask & (userMask | privMask);
}
else
mask = byte_mask & userMask;
u32 new_val = (cpu->CPSR.val & ~mask) | (operand & mask);
cpu->CPSR.val = (cpu->CPSR.val & ~mask) | (operand & mask);
cpu->changeCPSR();
#else
OP_MSR_CPSR_(operand);
#endif
return 1;
}
TEMPLATE static uint32_t FASTCALL OP_MSR_SPSR(uint32_t i)
{
//fprintf(stderr, "OP_MSR_SPSR\n");
uint32_t operand = cpu->R[REG_POS(i, 0)];
OP_MSR_SPSR_(operand);
return 1;
}
TEMPLATE static uint32_t FASTCALL OP_MSR_CPSR_IMM_VAL(uint32_t i)
{
//fprintf(stderr, "OP_MSR_CPSR_IMM_VAL\n");
IMM_VALUE;
OP_MSR_CPSR_(shift_op);
return 1;
}
TEMPLATE static uint32_t FASTCALL OP_MSR_SPSR_IMM_VAL(uint32_t i)
{
//fprintf(stderr, "OP_MSR_SPSR_IMM_VAL\n");
IMM_VALUE;
OP_MSR_SPSR_(shift_op);
return 1;
}
// -----------------------------------------------------------------------------
// Branch
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_BX(uint32_t i)
{
uint32_t tmp = cpu->R[REG_POS(i, 0)];
cpu->CPSR.bits.T = BIT0(tmp);
cpu->R[15] = tmp & (0xFFFFFFFC | (cpu->CPSR.bits.T << 1));
cpu->next_instruction = cpu->R[15];
return 3;
}
TEMPLATE static uint32_t FASTCALL OP_BLX_REG(uint32_t i)
{
uint32_t tmp = cpu->R[REG_POS(i, 0)];
cpu->R[14] = cpu->next_instruction;
cpu->CPSR.bits.T = BIT0(tmp);
cpu->R[15] = tmp & (0xFFFFFFFC | (cpu->CPSR.bits.T << 1));
cpu->next_instruction = cpu->R[15];
return 3;
}
static inline uint32_t SIGNEXTEND_24(uint32_t i) { return static_cast((static_cast(i) << 8) >> 8); }
TEMPLATE static uint32_t FASTCALL OP_B(uint32_t i)
{
/*static const uint32_t mov_r12_r12 = 0xE1A0C00C;
const uint32_t last = _MMU_read32(cpu->instruct_adr-4);
if(last == mov_r12_r12)
{
const uint32_t next = _MMU_read16(cpu->instruct_adr+4);
if(next == 0x6464)
NocashMessage(cpu, 8);
}*/
uint32_t off = SIGNEXTEND_24(i);
if (CONDITION(i) == 0xF)
{
cpu->R[14] = cpu->next_instruction;
cpu->CPSR.bits.T = 1;
}
cpu->R[15] += off << 2;
cpu->R[15] &= 0xFFFFFFFC | (cpu->CPSR.bits.T << 1);
cpu->next_instruction = cpu->R[15];
return 3;
}
TEMPLATE static uint32_t FASTCALL OP_BL(uint32_t i)
{
uint32_t off = SIGNEXTEND_24(i);
if (CONDITION(i) == 0xF)
{
cpu->CPSR.bits.T = 1;
cpu->R[15] += 2;
}
cpu->R[14] = cpu->next_instruction;
cpu->R[15] += off << 2;
cpu->R[15] &= 0xFFFFFFFC | (cpu->CPSR.bits.T << 1);
cpu->next_instruction = cpu->R[15];
return 3;
}
// -----------------------------------------------------------------------------
// CLZ
// -----------------------------------------------------------------------------
const uint8_t CLZ_TAB[]=
{
0, // 0000
1, // 0001
2, 2, // 001X
3, 3, 3, 3, // 01XX
4, 4, 4, 4, 4, 4, 4, 4 // 1XXX
};
TEMPLATE static uint32_t FASTCALL OP_CLZ(uint32_t i)
{
uint32_t Rm = cpu->R[REG_POS(i, 0)];
if (!Rm)
{
cpu->R[REG_POS(i, 12)] = 32;
return 2;
}
Rm |= Rm >> 1;
Rm |= Rm >> 2;
Rm |= Rm >> 4;
Rm |= Rm >> 8;
Rm |= Rm >> 16;
uint32_t pos = CLZ_TAB[Rm & 0xF] + CLZ_TAB[(Rm >> 4) & 0xF] + CLZ_TAB[(Rm >> 8) & 0xF] + CLZ_TAB[(Rm >> 12) & 0xF] +
CLZ_TAB[(Rm >> 16) & 0xF] + CLZ_TAB[(Rm >> 20) & 0xF] + CLZ_TAB[(Rm >> 24) & 0xF] + CLZ_TAB[(Rm >> 28) & 0xF];
cpu->R[REG_POS(i, 12)] = 32 - pos;
return 2;
}
// -----------------------------------------------------------------------------
// QADD / QDADD / QSUB / QDSUB
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_QADD(uint32_t i)
{
uint32_t res = cpu->R[REG_POS(i, 16)] + cpu->R[REG_POS(i, 0)];
if (SIGNED_OVERFLOW(cpu->R[REG_POS(i, 16)], cpu->R[REG_POS(i, 0)], res))
{
cpu->CPSR.bits.Q = 1;
cpu->R[REG_POS(i, 12)] = 0x80000000 - BIT31(res);
return 2;
}
cpu->R[REG_POS(i, 12)] = res;
if (REG_POS(i, 12) == 15)
{
cpu->R[15] &= 0xFFFFFFFC;
cpu->next_instruction = cpu->R[15];
return 3;
}
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_QSUB(uint32_t i)
{
uint32_t res = cpu->R[REG_POS(i, 0)] - cpu->R[REG_POS(i, 16)];
if (SIGNED_UNDERFLOW(cpu->R[REG_POS(i, 0)], cpu->R[REG_POS(i, 16)], res))
{
cpu->CPSR.bits.Q = 1;
cpu->R[REG_POS(i, 12)] = 0x80000000 - BIT31(res);
return 2;
}
cpu->R[REG_POS(i, 12)] = res;
if (REG_POS(i, 12) == 15)
{
cpu->R[15] &= 0xFFFFFFFC;
cpu->next_instruction = cpu->R[15];
return 3;
}
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_QDADD(uint32_t i)
{
uint32_t mul = cpu->R[REG_POS(i, 16)] << 1;
if (BIT31(cpu->R[REG_POS(i, 16)]) != BIT31(mul))
{
cpu->CPSR.bits.Q = 1;
mul = 0x80000000 - BIT31(mul);
}
uint32_t res = mul + cpu->R[REG_POS(i, 0)];
if (SIGNED_OVERFLOW(cpu->R[REG_POS(i, 0)], mul, res))
{
cpu->CPSR.bits.Q = 1;
cpu->R[REG_POS(i, 12)] = 0x80000000 - BIT31(res);
return 2;
}
cpu->R[REG_POS(i, 12)] = res;
if (REG_POS(i, 12) == 15)
{
cpu->R[15] &= 0xFFFFFFFC;
cpu->next_instruction = cpu->R[15];
return 3;
}
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_QDSUB(uint32_t i)
{
uint32_t mul = cpu->R[REG_POS(i, 16)] << 1;
if (BIT31(cpu->R[REG_POS(i, 16)]) != BIT31(mul))
{
cpu->CPSR.bits.Q = 1;
mul = 0x80000000 - BIT31(mul);
}
uint32_t res = cpu->R[REG_POS(i, 0)] - mul;
if (SIGNED_UNDERFLOW(cpu->R[REG_POS(i, 0)], mul, res))
{
cpu->CPSR.bits.Q = 1;
cpu->R[REG_POS(i, 12)] = 0x80000000 - BIT31(res);
return 2;
}
cpu->R[REG_POS(i, 12)] = res;
if (REG_POS(i, 12) == 15)
{
cpu->R[15] &= 0xFFFFFFFC;
cpu->next_instruction = cpu->R[15];
return 3;
}
return 2;
}
// -----------------------------------------------------------------------------
// SMUL
// -----------------------------------------------------------------------------
static inline int32_t HWORD(uint32_t i) { return static_cast(static_cast(i) >> 16); }
static inline int32_t LWORD(uint32_t i) { return static_cast(static_cast(i << 16) >> 16); }
TEMPLATE static uint32_t FASTCALL OP_SMUL_B_B(uint32_t i)
{
// checked
cpu->R[REG_POS(i, 16)] = static_cast(LWORD(cpu->R[REG_POS(i, 0)]) * LWORD(cpu->R[REG_POS(i, 8)]));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMUL_B_T(uint32_t i)
{
cpu->R[REG_POS(i, 16)] = static_cast(LWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMUL_T_B(uint32_t i)
{
cpu->R[REG_POS(i, 16)] = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * LWORD(cpu->R[REG_POS(i, 8)]));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMUL_T_T(uint32_t i)
{
cpu->R[REG_POS(i, 16)] = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
return 2;
}
// -----------------------------------------------------------------------------
// SMLA
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_SMLA_B_B(uint32_t i)
{
uint32_t tmp = static_cast(static_cast(cpu->R[REG_POS(i, 0)]) * static_cast(cpu->R[REG_POS(i, 8)]));
cpu->R[REG_POS(i, 16)] = tmp + cpu->R[REG_POS(i, 12)];
if (OverflowFromADD(cpu->R[REG_POS(i, 16)], tmp, cpu->R[REG_POS(i, 12)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLA_B_T(uint32_t i)
{
uint32_t tmp = static_cast(LWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
uint32_t a = cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 16)] = tmp + a;
if (SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i, 16)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLA_T_B(uint32_t i)
{
uint32_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * LWORD(cpu->R[REG_POS(i, 8)]));
uint32_t a = cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 16)] = tmp + a;
if (SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i, 16)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLA_T_T(uint32_t i)
{
uint32_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
uint32_t a = cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 16)] = tmp + a;
if (SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i, 16)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
// -----------------------------------------------------------------------------
// SMLAL
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_SMLAL_B_B(uint32_t i)
{
int64_t tmp = static_cast(LWORD(cpu->R[REG_POS(i, 0)]) * LWORD(cpu->R[REG_POS(i, 8)]));
uint64_t res = static_cast(tmp) + cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] += static_cast(res + ((tmp < 0) * 0xFFFFFFFF));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLAL_B_T(uint32_t i)
{
int64_t tmp = static_cast(LWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
uint64_t res = static_cast(tmp) + cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] += static_cast(res + ((tmp < 0) * 0xFFFFFFFF));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLAL_T_B(uint32_t i)
{
int64_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * static_cast(LWORD(cpu->R[REG_POS(i, 8)])));
uint64_t res = static_cast(tmp) + cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] += static_cast(res + ((tmp < 0) * 0xFFFFFFFF));
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLAL_T_T(uint32_t i)
{
int64_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 0)]) * HWORD(cpu->R[REG_POS(i, 8)]));
uint64_t res = static_cast(tmp) + cpu->R[REG_POS(i, 12)];
cpu->R[REG_POS(i, 12)] = static_cast(res);
cpu->R[REG_POS(i, 16)] += static_cast(res + ((tmp < 0) * 0xFFFFFFFF));
return 2;
}
// -----------------------------------------------------------------------------
// SMULW
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_SMULW_B(uint32_t i)
{
int64_t tmp = static_cast(LWORD(cpu->R[REG_POS(i, 8)])) * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
cpu->R[REG_POS(i, 16)] = (tmp >> 16) & 0xFFFFFFFF;
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMULW_T(uint32_t i)
{
int64_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 8)])) * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
cpu->R[REG_POS(i, 16)] = (tmp >> 16) & 0xFFFFFFFF;
return 2;
}
// -----------------------------------------------------------------------------
// SMLAW
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_SMLAW_B(uint32_t i)
{
int64_t tmp = static_cast(LWORD(cpu->R[REG_POS(i, 8)])) * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
uint32_t a = cpu->R[REG_POS(i, 12)];
tmp >>= 16;
cpu->R[REG_POS(i, 16)] = static_cast(tmp + a);
if (SIGNED_OVERFLOW(static_cast(tmp), a, cpu->R[REG_POS(i, 16)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
TEMPLATE static uint32_t FASTCALL OP_SMLAW_T(uint32_t i)
{
int64_t tmp = static_cast(HWORD(cpu->R[REG_POS(i, 8)])) * static_cast(static_cast(cpu->R[REG_POS(i, 0)]));
uint32_t a = cpu->R[REG_POS(i, 12)];
tmp = (tmp >> 16) & 0xFFFFFFFF;
cpu->R[REG_POS(i, 16)] = static_cast(tmp + a);
if (SIGNED_OVERFLOW(static_cast(tmp), a, cpu->R[REG_POS(i, 16)]))
cpu->CPSR.bits.Q = 1;
return 2;
}
// -----------------------------------------------------------------------------
// LDR
// -----------------------------------------------------------------------------
#define OP_LDR(a, b) \
cpu->R[REG_POS(i, 12)] = ROR(READ32(cpu->mem_if->data, adr), 8 * (adr & 3)); \
\
if (REG_POS(i, 12) == 15) \
{ \
if (!PROCNUM) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
} \
else \
cpu->R[15] &= 0xFFFFFFFC; \
cpu->next_instruction = cpu->R[15]; \
return MMU_aluMemAccessCycles(b, adr); \
} \
\
return MMU_aluMemAccessCycles(a, adr);
// PRE
#define OP_LDR_W(a, b) \
cpu->R[REG_POS(i, 16)] = adr;\
cpu->R[REG_POS(i, 12)] = ROR(READ32(cpu->mem_if->data, adr), 8 * (adr & 3)); \
\
if (REG_POS(i, 12) == 15) \
{ \
if (!PROCNUM) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
} \
else \
cpu->R[15] &= 0xFFFFFFFC; \
cpu->next_instruction = cpu->R[15]; \
return MMU_aluMemAccessCycles(b, adr); \
} \
\
return MMU_aluMemAccessCycles(a, adr);
// POST
#define OP_LDR_W2(a, b, c) \
uint32_t adr = cpu->R[REG_POS(i, 16)]; \
cpu->R[REG_POS(i, 16)] = adr + c;\
cpu->R[REG_POS(i, 12)] = ROR(READ32(cpu->mem_if->data, adr), 8 * (adr & 3)); \
\
if (REG_POS(i, 12) == 15) \
{ \
if (!PROCNUM) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
} \
else \
cpu->R[15] &= 0xFFFFFFFC; \
cpu->next_instruction = cpu->R[15]; \
return MMU_aluMemAccessCycles(b, adr); \
} \
\
return MMU_aluMemAccessCycles(a, adr);
TEMPLATE static uint32_t FASTCALL OP_LDR_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF_12;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF_12;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSL_IMM_OFF(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSL_IMM_OFF(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSR_IMM_OFF(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSR_IMM_OFF(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ASR_IMM_OFF(uint32_t i)
{
ASR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ASR_IMM_OFF(uint32_t i)
{
ASR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ROR_IMM_OFF(uint32_t i)
{
ROR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ROR_IMM_OFF(uint32_t i)
{
ROR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_IMM_OFF_PREIND(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF_12;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_IMM_OFF_PREIND(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF_12;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSL_IMM_OFF_PREIND(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSL_IMM_OFF_PREIND(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSR_IMM_OFF_PREIND(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSR_IMM_OFF_PREIND(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ASR_IMM_OFF_PREIND(uint32_t i)
{
ASR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ASR_IMM_OFF_PREIND(uint32_t i)
{
ASR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ROR_IMM_OFF_PREIND(uint32_t i)
{
ROR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ROR_IMM_OFF_PREIND(uint32_t i)
{
ROR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
OP_LDR_W(3, 5);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_IMM_OFF_POSTIND(uint32_t i)
{
OP_LDR_W2(3, 5, IMM_OFF_12);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_IMM_OFF_POSTIND(uint32_t i)
{
OP_LDR_W2(3, 5, -IMM_OFF_12);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(uint32_t i)
{
LSL_IMM;
OP_LDR_W2(3, 5, shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(uint32_t i)
{
LSL_IMM;
OP_LDR_W2(3, 5, -shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(uint32_t i)
{
LSR_IMM;
OP_LDR_W2(3, 5, shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(uint32_t i)
{
LSR_IMM;
OP_LDR_W2(3, 5, -shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(uint32_t i)
{
ASR_IMM;
OP_LDR_W2(3, 5, shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(uint32_t i)
{
ASR_IMM;
OP_LDR_W2(3, 5, -shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(uint32_t i)
{
ROR_IMM;
OP_LDR_W2(3, 5, shift_op);
}
TEMPLATE static uint32_t FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(uint32_t i)
{
ROR_IMM;
OP_LDR_W2(3, 5, -shift_op);
}
// -----------------------------------------------------------------------------
// LDREX
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_LDREX(uint32_t i)
{
fprintf(stderr, "LDREX\n");
uint32_t adr = cpu->R[REG_POS(i, 16)];
cpu->R[REG_POS(i, 12)] = ROR(READ32(cpu->mem_if->data, adr), 8 * (adr & 3));
return MMU_aluMemAccessCycles(3, adr);
}
// -----------------------------------------------------------------------------
// LDRB
// -----------------------------------------------------------------------------
TEMPLATE static uint32_t FASTCALL OP_LDRB_P_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] + IMM_OFF_12;
cpu->R[REG_POS(i, 12)] = static_cast(READ8(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRB_M_IMM_OFF(uint32_t i)
{
uint32_t adr = cpu->R[REG_POS(i, 16)] - IMM_OFF_12;
cpu->R[REG_POS(i, 12)] = static_cast(READ8(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSL_IMM_OFF(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
cpu->R[REG_POS(i, 12)] = static_cast(READ8(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSL_IMM_OFF(uint32_t i)
{
LSL_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
cpu->R[REG_POS(i, 12)] = static_cast(READ8(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSR_IMM_OFF(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] + shift_op;
cpu->R[REG_POS(i, 12)] = READ8(cpu->mem_if->data, adr);
return MMU_aluMemAccessCycles(3, adr);
}
TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSR_IMM_OFF(uint32_t i)
{
LSR_IMM;
uint32_t adr = cpu->R[REG_POS(i, 16)] - shift_op;
cpu->R[REG_POS(i, 12)] = static_cast(READ8(cpu->mem_if->data, adr));
return MMU_aluMemAccessCycles