/* 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) //#define UNTESTEDOPCODEDEBUG #include "cp15.h" //#include "debug.h" #include "MMU.h" #include "armcpu.h" #include "NDSSystem.h" #include "arm_instructions.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==0) \ 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)]<R[REG_POS(i,8)])&0xFF; \ if(shift_op>=32) \ shift_op=0; \ else \ shift_op=cpu->R[REG_POS(i,0)]<R[REG_POS(i,8)])&0xFF; \ uint32_t c = cpu->CPSR.bits.C; \ if(shift_op==0) \ 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)]<R[REG_POS(i,0)]); \ } \ else \ { \ shift_op = 0; \ c = 0; \ } #define LSR_IMM \ uint32_t shift_op = ((i>>7)&0x1F); \ if(shift_op!=0) \ 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==0) \ { \ 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==0) \ { \ 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==0) \ shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; \ else \ shift_op = (uint32_t)((int32_t)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==0) \ { \ 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 = (uint32_t)((int32_t)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==0) \ shift_op=cpu->R[REG_POS(i,0)]; \ else \ if(shift_op<32) \ shift_op = (uint32_t)((int32_t)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==0) \ 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 = (uint32_t)((int32_t)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==0) \ { \ shift_op = ((uint32_t)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==0) \ { \ shift_op = ((uint32_t)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==0)||((shift_op&0x1F)==0)) \ 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==0) \ shift_op=cpu->R[REG_POS(i,0)]; \ else \ { \ shift_op&=0x1F; \ if(shift_op==0) \ { \ 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(const 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|(((uint32_t)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)]==0); \ return a; TEMPLATE static uint32_t FASTCALL OP_AND_LSL_IMM(const uint32_t i) { LSL_IMM; OP_AND(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_LSL_REG(const uint32_t i) { LSL_REG; OP_AND(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_LSR_IMM(const uint32_t i) { LSR_IMM; OP_AND(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_LSR_REG(const uint32_t i) { LSR_REG; OP_AND(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_ASR_IMM(const uint32_t i) { ASR_IMM; OP_AND(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_ASR_REG(const uint32_t i) { ASR_REG; OP_AND(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_ROR_IMM(const uint32_t i) { ROR_IMM; OP_AND(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_ROR_REG(const uint32_t i) { ROR_REG; OP_AND(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_AND(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_ANDS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_S_LSL_REG(const uint32_t i) { S_LSL_REG; OP_ANDS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_S_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_ANDS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_S_LSR_REG(const uint32_t i) { S_LSR_REG; OP_ANDS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_S_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_ANDS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_ANDS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_ANDS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_AND_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_ANDS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_AND_S_IMM_VAL(const 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|(((uint32_t)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)]==0); \ return a; TEMPLATE static uint32_t FASTCALL OP_EOR_LSL_IMM(const uint32_t i) { LSL_IMM; OP_EOR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_LSL_REG(const uint32_t i) { LSL_REG; OP_EOR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_LSR_IMM(const uint32_t i) { LSR_IMM; OP_EOR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_LSR_REG(const uint32_t i) { LSR_REG; OP_EOR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_ASR_IMM(const uint32_t i) { ASR_IMM; OP_EOR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_ASR_REG(const uint32_t i) { ASR_REG; OP_EOR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_ROR_IMM(const uint32_t i) { ROR_IMM; OP_EOR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_ROR_REG(const uint32_t i) { ROR_REG; OP_EOR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_EOR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_EORS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSL_REG(const uint32_t i) { S_LSL_REG; OP_EORS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_EORS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_LSR_REG(const uint32_t i) { S_LSR_REG; OP_EORS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_EORS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_EORS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_EORS(1, 3); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_EORS(2, 4); } TEMPLATE static uint32_t FASTCALL OP_EOR_S_IMM_VAL(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_SUB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SUB_LSL_REG(const uint32_t i) { LSL_REG; OP_SUB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SUB_LSR_IMM(const uint32_t i) { LSR_IMM; OP_SUB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SUB_LSR_REG(const uint32_t i) { LSR_REG; OP_SUB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SUB_ASR_IMM(const uint32_t i) { ASR_IMM; OP_SUB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SUB_ASR_REG(const uint32_t i) { ASR_REG; OP_SUB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SUB_ROR_IMM(const uint32_t i) { ROR_IMM; OP_SUB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SUB_ROR_REG(const uint32_t i) { ROR_REG; OP_SUB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SUB_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_SUB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SUB_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_RSB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSB_LSL_REG(const uint32_t i) { LSL_REG; OP_RSB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSB_LSR_IMM(const uint32_t i) { LSR_IMM; OP_RSB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSB_LSR_REG(const uint32_t i) { LSR_REG; OP_RSB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSB_ASR_IMM(const uint32_t i) { ASR_IMM; OP_RSB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSB_ASR_REG(const uint32_t i) { ASR_REG; OP_RSB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSB_ROR_IMM(const uint32_t i) { ROR_IMM; OP_RSB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSB_ROR_REG(const uint32_t i) { ROR_REG; OP_RSB(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSB_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_RSB(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSB_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_ADD(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADD_LSL_REG(const uint32_t i) { LSL_REG; OP_ADD(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADD_LSR_IMM(const uint32_t i) { LSR_IMM; OP_ADD(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADD_LSR_REG(const uint32_t i) { LSR_REG; OP_ADD(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADD_ASR_IMM(const uint32_t i) { ASR_IMM; OP_ADD(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADD_ASR_REG(const uint32_t i) { ASR_REG; OP_ADD(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADD_ROR_IMM(const uint32_t i) { ROR_IMM; OP_ADD(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADD_ROR_REG(const uint32_t i) { ROR_REG; OP_ADD(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADD_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_ADD(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADD_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_ADC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADC_LSL_REG(const uint32_t i) { LSL_REG; OP_ADC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADC_LSR_IMM(const uint32_t i) { LSR_IMM; OP_ADC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADC_LSR_REG(const uint32_t i) { LSR_REG; OP_ADC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADC_ASR_IMM(const uint32_t i) { ASR_IMM; OP_ADC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADC_ASR_REG(const uint32_t i) { ASR_REG; OP_ADC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADC_ROR_IMM(const uint32_t i) { ROR_IMM; OP_ADC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADC_ROR_REG(const uint32_t i) { ROR_REG; OP_ADC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ADC_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_ADC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ADC_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_SBC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SBC_LSL_REG(const uint32_t i) { LSL_REG; OP_SBC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SBC_LSR_IMM(const uint32_t i) { LSR_IMM; OP_SBC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SBC_LSR_REG(const uint32_t i) { LSR_REG; OP_SBC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SBC_ASR_IMM(const uint32_t i) { ASR_IMM; OP_SBC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SBC_ASR_REG(const uint32_t i) { ASR_REG; OP_SBC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SBC_ROR_IMM(const uint32_t i) { ROR_IMM; OP_SBC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SBC_ROR_REG(const uint32_t i) { ROR_REG; OP_SBC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_SBC_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_SBC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_SBC_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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|(((uint32_t)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)]==0); \ 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(const uint32_t i) { LSL_IMM; OP_RSC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSC_LSL_REG(const uint32_t i) { LSL_REG; OP_RSC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSC_LSR_IMM(const uint32_t i) { LSR_IMM; OP_RSC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSC_LSR_REG(const uint32_t i) { LSR_REG; OP_RSC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSC_ASR_IMM(const uint32_t i) { ASR_IMM; OP_RSC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSC_ASR_REG(const uint32_t i) { ASR_REG; OP_RSC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSC_ROR_IMM(const uint32_t i) { ROR_IMM; OP_RSC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSC_ROR_REG(const uint32_t i) { ROR_REG; OP_RSC(2, 4); } TEMPLATE static uint32_t FASTCALL OP_RSC_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_RSC(1, 3); } TEMPLATE static uint32_t FASTCALL OP_RSC_S_LSL_IMM(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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==0); \ return a; \ } TEMPLATE static uint32_t FASTCALL OP_TST_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_TST(1); } TEMPLATE static uint32_t FASTCALL OP_TST_LSL_REG(const uint32_t i) { S_LSL_REG; OP_TST(2); } TEMPLATE static uint32_t FASTCALL OP_TST_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_TST(1); } TEMPLATE static uint32_t FASTCALL OP_TST_LSR_REG(const uint32_t i) { S_LSR_REG; OP_TST(2); } TEMPLATE static uint32_t FASTCALL OP_TST_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_TST(1); } TEMPLATE static uint32_t FASTCALL OP_TST_ASR_REG(const uint32_t i) { S_ASR_REG; OP_TST(2); } TEMPLATE static uint32_t FASTCALL OP_TST_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_TST(1); } TEMPLATE static uint32_t FASTCALL OP_TST_ROR_REG(const uint32_t i) { S_ROR_REG; OP_TST(2); } TEMPLATE static uint32_t FASTCALL OP_TST_IMM_VAL(const 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==0); \ return a; \ } TEMPLATE static uint32_t FASTCALL OP_TEQ_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_TEQ(1); } TEMPLATE static uint32_t FASTCALL OP_TEQ_LSL_REG(const uint32_t i) { S_LSL_REG; OP_TEQ(2); } TEMPLATE static uint32_t FASTCALL OP_TEQ_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_TEQ(1); } TEMPLATE static uint32_t FASTCALL OP_TEQ_LSR_REG(const uint32_t i) { S_LSR_REG; OP_TEQ(2); } TEMPLATE static uint32_t FASTCALL OP_TEQ_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_TEQ(1); } TEMPLATE static uint32_t FASTCALL OP_TEQ_ASR_REG(const uint32_t i) { S_ASR_REG; OP_TEQ(2); } TEMPLATE static uint32_t FASTCALL OP_TEQ_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_TEQ(1); } TEMPLATE static uint32_t FASTCALL OP_TEQ_ROR_REG(const uint32_t i) { S_ROR_REG; OP_TEQ(2); } TEMPLATE static uint32_t FASTCALL OP_TEQ_IMM_VAL(const 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==0); \ 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(const uint32_t i) { LSL_IMM; OP_CMP(1); } TEMPLATE static uint32_t FASTCALL OP_CMP_LSL_REG(const uint32_t i) { LSL_REG; OP_CMP(2); } TEMPLATE static uint32_t FASTCALL OP_CMP_LSR_IMM(const uint32_t i) { LSR_IMM; OP_CMP(1); } TEMPLATE static uint32_t FASTCALL OP_CMP_LSR_REG(const uint32_t i) { LSR_REG; OP_CMP(2); } TEMPLATE static uint32_t FASTCALL OP_CMP_ASR_IMM(const uint32_t i) { ASR_IMM; OP_CMP(1); } TEMPLATE static uint32_t FASTCALL OP_CMP_ASR_REG(const uint32_t i) { ASR_REG; OP_CMP(2); } TEMPLATE static uint32_t FASTCALL OP_CMP_ROR_IMM(const uint32_t i) { ROR_IMM; OP_CMP(1); } TEMPLATE static uint32_t FASTCALL OP_CMP_ROR_REG(const uint32_t i) { ROR_REG; OP_CMP(2); } TEMPLATE static uint32_t FASTCALL OP_CMP_IMM_VAL(const 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==0); \ 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(const uint32_t i) { LSL_IMM; OP_CMN(1); } TEMPLATE static uint32_t FASTCALL OP_CMN_LSL_REG(const uint32_t i) { LSL_REG; OP_CMN(2); } TEMPLATE static uint32_t FASTCALL OP_CMN_LSR_IMM(const uint32_t i) { LSR_IMM; OP_CMN(1); } TEMPLATE static uint32_t FASTCALL OP_CMN_LSR_REG(const uint32_t i) { LSR_REG; OP_CMN(2); } TEMPLATE static uint32_t FASTCALL OP_CMN_ASR_IMM(const uint32_t i) { ASR_IMM; OP_CMN(1); } TEMPLATE static uint32_t FASTCALL OP_CMN_ASR_REG(const uint32_t i) { ASR_REG; OP_CMN(2); } TEMPLATE static uint32_t FASTCALL OP_CMN_ROR_IMM(const uint32_t i) { ROR_IMM; OP_CMN(1); } TEMPLATE static uint32_t FASTCALL OP_CMN_ROR_REG(const uint32_t i) { ROR_REG; OP_CMN(2); } TEMPLATE static uint32_t FASTCALL OP_CMN_IMM_VAL(const 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|(((uint32_t)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)]==0); \ return a; \ } TEMPLATE static uint32_t FASTCALL OP_ORR_LSL_IMM(const uint32_t i) { LSL_IMM; OP_ORR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ORR_LSL_REG(const uint32_t i) { LSL_REG; OP_ORR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ORR_LSR_IMM(const uint32_t i) { LSR_IMM; OP_ORR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ORR_LSR_REG(const uint32_t i) { LSR_REG; OP_ORR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ORR_ASR_IMM(const uint32_t i) { ASR_IMM; OP_ORR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ORR_ASR_REG(const uint32_t i) { ASR_REG; OP_ORR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ORR_ROR_IMM(const uint32_t i) { ROR_IMM; OP_ORR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ORR_ROR_REG(const uint32_t i) { ROR_REG; OP_ORR(2, 4); } TEMPLATE static uint32_t FASTCALL OP_ORR_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_ORR(1, 3); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_ORRS(1,3); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSL_REG(const uint32_t i) { S_LSL_REG; OP_ORRS(2,4); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_ORRS(1,3); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_LSR_REG(const uint32_t i) { S_LSR_REG; OP_ORRS(2,4); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_ORRS(1,3); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_ORRS(2,4); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_ORRS(1,3); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_ORRS(2,4); } TEMPLATE static uint32_t FASTCALL OP_ORR_S_IMM_VAL(const 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|(((uint32_t)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)]==0); \ return a; \ TEMPLATE static uint32_t FASTCALL OP_MOV_LSL_IMM(const uint32_t i) { LSL_IMM; OP_MOV(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_LSL_REG(const 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(const uint32_t i) { LSR_IMM; OP_MOV(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_LSR_REG(const 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(const uint32_t i) { ASR_IMM; OP_MOV(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_ASR_REG(const uint32_t i) { ASR_REG; OP_MOV(2,4); } TEMPLATE static uint32_t FASTCALL OP_MOV_ROR_IMM(const uint32_t i) { ROR_IMM; OP_MOV(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_ROR_REG(const uint32_t i) { ROR_REG; OP_MOV(2,4); } TEMPLATE static uint32_t FASTCALL OP_MOV_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_MOV(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_MOVS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSL_REG(const 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(const uint32_t i) { S_LSR_IMM; OP_MOVS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_LSR_REG(const 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(const uint32_t i) { S_ASR_IMM; OP_MOVS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_MOVS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_MOVS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_MOVS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MOV_S_IMM_VAL(const 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|(((uint32_t)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)]==0); \ return a; TEMPLATE static uint32_t FASTCALL OP_BIC_LSL_IMM(const uint32_t i) { LSL_IMM; OP_BIC(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_LSL_REG(const uint32_t i) { LSL_REG; OP_BIC(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_LSR_IMM(const uint32_t i) { LSR_IMM; OP_BIC(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_LSR_REG(const uint32_t i) { LSR_REG; OP_BIC(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_ASR_IMM(const uint32_t i) { ASR_IMM; OP_BIC(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_ASR_REG(const uint32_t i) { ASR_REG; OP_BIC(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_ROR_IMM(const uint32_t i) { ROR_IMM; OP_BIC(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_ROR_REG(const uint32_t i) { ROR_REG; OP_BIC(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_BIC(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_BICS(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSL_REG(const uint32_t i) { S_LSL_REG; OP_BICS(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_BICS(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_LSR_REG(const uint32_t i) { S_LSR_REG; OP_BICS(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_BICS(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_BICS(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_BICS(1,3); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_BICS(2,4); } TEMPLATE static uint32_t FASTCALL OP_BIC_S_IMM_VAL(const 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|(((uint32_t)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)]==0); \ return a; TEMPLATE static uint32_t FASTCALL OP_MVN_LSL_IMM(const uint32_t i) { LSL_IMM; OP_MVN(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_LSL_REG(const uint32_t i) { LSL_REG; OP_MVN(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_LSR_IMM(const uint32_t i) { LSR_IMM; OP_MVN(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_LSR_REG(const uint32_t i) { LSR_REG; OP_MVN(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_ASR_IMM(const uint32_t i) { ASR_IMM; OP_MVN(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_ASR_REG(const uint32_t i) { ASR_REG; OP_MVN(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_ROR_IMM(const uint32_t i) { ROR_IMM; OP_MVN(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_ROR_REG(const uint32_t i) { ROR_REG; OP_MVN(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_IMM_VAL(const uint32_t i) { IMM_VALUE; OP_MVN(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSL_IMM(const uint32_t i) { S_LSL_IMM; OP_MVNS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSL_REG(const uint32_t i) { S_LSL_REG; OP_MVNS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSR_IMM(const uint32_t i) { S_LSR_IMM; OP_MVNS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_LSR_REG(const uint32_t i) { S_LSR_REG; OP_MVNS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_ASR_IMM(const uint32_t i) { S_ASR_IMM; OP_MVNS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_ASR_REG(const uint32_t i) { S_ASR_REG; OP_MVNS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_ROR_IMM(const uint32_t i) { S_ROR_IMM; OP_MVNS(1,3); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_ROR_REG(const uint32_t i) { S_ROR_REG; OP_MVNS(2,4); } TEMPLATE static uint32_t FASTCALL OP_MVN_S_IMM_VAL(const uint32_t i) { S_IMM_VALUE; OP_MVNS(1,3); } //----------------------------------------------------------------------------- // MUL / MULS / MLA / MLAS //----------------------------------------------------------------------------- #define MUL_Mxx_END(c) \ v >>= 8; \ if((v==0)||(v==0xFFFFFF)) \ return c+1; \ v >>= 8; \ if((v==0)||(v==0xFFFF)) \ return c+2; \ v >>= 8; \ if((v==0)||(v==0xFF)) \ return c+3; \ return c+4; \ TEMPLATE static uint32_t FASTCALL OP_MUL(const 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(const 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(const 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)]==0); MUL_Mxx_END(1); } TEMPLATE static uint32_t FASTCALL OP_MLA_S(const 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)]==0); MUL_Mxx_END(2); } //----------------------------------------------------------------------------- // UMULL / UMULLS / UMLAL / UMLALS //----------------------------------------------------------------------------- #define MUL_UMxxL_END(c) \ v >>= 8; \ if(v==0) \ return c+1; \ v >>= 8; \ if(v==0) \ return c+2; \ v >>= 8; \ if(v==0) \ return c+3; \ return c+4; \ TEMPLATE static uint32_t FASTCALL OP_UMULL(const uint32_t i) { uint32_t v = cpu->R[REG_POS(i,8)]; uint64_t res = (uint64_t)cpu->R[REG_POS(i,0)] * (uint64_t)v; cpu->R[REG_POS(i,12)] = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(res>>32); MUL_UMxxL_END(2); } TEMPLATE static uint32_t FASTCALL OP_UMLAL(const uint32_t i) { uint32_t v = cpu->R[REG_POS(i,8)]; uint64_t res = (uint64_t)cpu->R[REG_POS(i,0)] * (uint64_t)v; // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) uint32_t tmp = (uint32_t)res; // low cpu->R[REG_POS(i,16)] = (uint32_t)(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(const uint32_t i) { uint32_t v = cpu->R[REG_POS(i,8)]; uint64_t res = ((uint64_t)cpu->R[REG_POS(i,0)] * (uint64_t)v); cpu->R[REG_POS(i,12)] = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(res>>32); cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) && (cpu->R[REG_POS(i,12)]==0); MUL_UMxxL_END(2); } TEMPLATE static uint32_t FASTCALL OP_UMLAL_S(const uint32_t i) { uint32_t v = cpu->R[REG_POS(i,8)]; uint64_t res = (uint64_t)cpu->R[REG_POS(i,0)] * (uint64_t)v; // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) uint32_t tmp = (uint32_t)res; // low cpu->R[REG_POS(i,16)] = (uint32_t)(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)]==0) & (cpu->R[REG_POS(i,12)]==0); MUL_UMxxL_END(3); } //----------------------------------------------------------------------------- // SMULL / SMULLS / SMLAL / SMLALS //----------------------------------------------------------------------------- #define MUL_SMxxL_END(c) \ v &= 0xFFFFFFFF; \ v >>= 8; \ if((v==0)||(v==0xFFFFFF)) \ return c+1; \ v >>= 8; \ if((v==0)||(v==0xFFFF)) \ return c+2; \ v >>= 8; \ if((v==0)||(v==0xFF)) \ return c+3; \ return c+4; \ TEMPLATE static uint32_t FASTCALL OP_SMULL(const uint32_t i) { int64_t v = (int32_t)cpu->R[REG_POS(i,8)]; int64_t res = v * (int64_t)(int32_t)cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(res>>32); MUL_SMxxL_END(2); } TEMPLATE static uint32_t FASTCALL OP_SMLAL(const uint32_t i) { int64_t v = (int32_t)cpu->R[REG_POS(i,8)]; int64_t res = v * (int64_t)(int32_t)cpu->R[REG_POS(i,0)]; //LOG("%08X * %08X + %08X%08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]); uint32_t tmp = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,12)] += tmp; //LOG("= %08X%08X %08X%08X\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res); MUL_SMxxL_END(3); } TEMPLATE static uint32_t FASTCALL OP_SMULL_S(const uint32_t i) { int64_t v = (int32_t)cpu->R[REG_POS(i,8)]; int64_t res = v * (int64_t)(int32_t)cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(res>>32); cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); MUL_SMxxL_END(2); } TEMPLATE static uint32_t FASTCALL OP_SMLAL_S(const uint32_t i) { int64_t v = (int32_t)cpu->R[REG_POS(i,8)]; int64_t res = v * (int64_t)(int32_t)cpu->R[REG_POS(i,0)]; uint32_t tmp = (uint32_t)res; cpu->R[REG_POS(i,16)] = (uint32_t)(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)]==0) & (cpu->R[REG_POS(i,12)]==0); MUL_SMxxL_END(3); } //----------------------------------------------------------------------------- // SWP / SWPB //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_SWP(const 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(const 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, (uint8_t)(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(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,12)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,12)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_P_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_M_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(const 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)] =(uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(const 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)] = (uint32_t)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // STRH //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_STRH_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF; WRITE16(cpu->mem_if->data, adr, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF; WRITE16(cpu->mem_if->data, adr, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_P_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_M_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(const 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, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(const 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, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(const 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, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(const 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, (uint16_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)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(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)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(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)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(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE16(cpu->mem_if->data, adr, (uint16_t)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(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,12)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,12)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_P_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_M_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(const 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)] = (int32_t)((int16_t)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // LDRSB //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_LDRSB_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,12)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,12)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_P_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_M_REG_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(const 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)] = (int32_t)((int8_t)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // MRS / MSR //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_MRS_CPSR(const uint32_t i) { cpu->R[REG_POS(i,12)] = cpu->CPSR.val; return 1; } TEMPLATE static uint32_t FASTCALL OP_MRS_SPSR(const uint32_t i) { cpu->R[REG_POS(i,12)] = cpu->SPSR.val; return 1; } #define v4_UNALLOC_MASK 0x0FFFFF00 #define v4_USER_MASK 0xF0000000 #define v4_PRIV_MASK 0x0000000F #define v4_STATE_MASK 0x00000020 #define v5_UNALLOC_MASK 0x07FFFF00 #define v5_USER_MASK 0xF8000000 #define v5_PRIV_MASK 0x0000000F #define v5_STATE_MASK 0x00000020 TEMPLATE static uint32_t FASTCALL OP_MSR_CPSR(const uint32_t i) { uint32_t operand = cpu->R[REG_POS(i,0)]; #if 0 // TODO uint32_t mask = 0; uint32_t byte_mask = (BIT16(i)?0x000000FF:0x00000000) | (BIT17(i)?0x0000FF00:0x00000000) | (BIT18(i)?0x00FF0000:0x00000000) | (BIT19(i)?0xFF000000:0x00000000); if (PROCNUM == 0) { if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); if (cpu->CPSR.bits.mode != USR) // Privileged mode { if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand); mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK); } else mask = byte_mask & v5_USER_MASK; } else { if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); if(cpu->CPSR.bits.mode != USR) // Privileged mode { if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand); mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK); } else mask = byte_mask & v4_USER_MASK; } cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode); cpu->changeCPSR(); #else if(cpu->CPSR.bits.mode!=USR) { if(BIT16(i)) { armcpu_switchMode(cpu, operand & 0x1F); cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF); } if(BIT17(i)) cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00); if(BIT18(i)) cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); } if(BIT19(i)) cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); cpu->changeCPSR(); #endif return 1; } TEMPLATE static uint32_t FASTCALL OP_MSR_SPSR(const uint32_t i) { uint32_t operand = cpu->R[REG_POS(i,0)]; #if 0 // TODO uint32_t mask = 0; uint32_t byte_mask = (BIT16(i)?0x000000FF:0x00000000) | (BIT17(i)?0x0000FF00:0x00000000) | (BIT18(i)?0x00FF0000:0x00000000) | (BIT19(i)?0xFF000000:0x00000000); if (PROCNUM == 0) { if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); // if CurrentModeHasSPSR mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK); } else { if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); // if CurrentModeHasSPSR mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK); } cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask)); cpu->changeCPSR(); #else if(cpu->CPSR.bits.mode!=USR) { if(BIT16(i)) { cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0xFF); } if(BIT17(i)) cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0xFF00); if(BIT18(i)) cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); } if(BIT19(i)) cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); #endif return 1; } TEMPLATE static uint32_t FASTCALL OP_MSR_CPSR_IMM_VAL(const uint32_t i) { IMM_VALUE; #if 0 // TODO uint32_t operand = shift_op; uint32_t mask = 0; uint32_t byte_mask = (BIT16(i)?0x000000FF:0x00000000) | (BIT17(i)?0x0000FF00:0x00000000) | (BIT18(i)?0x00FF0000:0x00000000) | (BIT19(i)?0xFF000000:0x00000000); if (PROCNUM == 0) { if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); if (cpu->CPSR.bits.mode != USR) // Privileged mode { if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand); mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK); } else mask = byte_mask & v5_USER_MASK; } else { if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); if(cpu->CPSR.bits.mode != USR) // Privileged mode { if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand); mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK); } else mask = byte_mask & v4_USER_MASK; } cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode); cpu->changeCPSR(); #else if(cpu->CPSR.bits.mode!=USR) { if(BIT16(i)) { armcpu_switchMode(cpu, shift_op & 0x1F); cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0xFF); } if(BIT17(i)) cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00); if(BIT18(i)) cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000); } if(BIT19(i)) { //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0xFF000000); cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000); } cpu->changeCPSR(); #endif return 1; } TEMPLATE static uint32_t FASTCALL OP_MSR_SPSR_IMM_VAL(const uint32_t i) { IMM_VALUE; #if 0 // TODO uint32_t operand = shift_op; uint32_t mask = 0; uint32_t byte_mask = (BIT16(i)?0x000000FF:0x00000000) | (BIT17(i)?0x0000FF00:0x00000000) | (BIT18(i)?0x00FF0000:0x00000000) | (BIT19(i)?0xFF000000:0x00000000); if (PROCNUM == 0) { if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); // if CurrentModeHasSPSR mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK); } else { if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); // if CurrentModeHasSPSR mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK); } cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask)); #else if(cpu->CPSR.bits.mode!=USR) { if(BIT16(i)) { cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0xFF); } if(BIT17(i)) cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00); if(BIT18(i)) cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000); } if(BIT19(i)) { cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0xFF000000); } cpu->changeCPSR(); #endif return 1; } //----------------------------------------------------------------------------- // Branch //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_BX(const uint32_t i) { uint32_t tmp = cpu->R[REG_POS(i, 0)]; if (REG_POS(i, 0) == 15) { //printf("ARM%c: BX using PC as operand\n", PROCNUM?'7':'9'); //emu_halt(); } 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(const 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; } #define SIGNEXTEND_24(i) (((int32_t)i<<8)>>8) TEMPLATE static uint32_t FASTCALL OP_B(const 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(const 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[16]= { 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(const uint32_t i) { uint32_t Rm = cpu->R[REG_POS(i,0)]; uint32_t pos; if(Rm==0) { cpu->R[REG_POS(i,12)]=32; return 2; } Rm |= (Rm >>1); Rm |= (Rm >>2); Rm |= (Rm >>4); Rm |= (Rm >>8); Rm |= (Rm >>16); 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(const uint32_t i) { uint32_t res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)]; //LOG("spe add\n"); 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(const uint32_t i) { uint32_t res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)]; //LOG("spe add\n"); 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(const uint32_t i) { uint32_t mul = cpu->R[REG_POS(i,16)]<<1; uint32_t res; //LOG("spe add\n"); if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) { cpu->CPSR.bits.Q=1; mul = 0x80000000-BIT31(mul); } 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(const uint32_t i) { uint32_t mul = cpu->R[REG_POS(i,16)]<<1; uint32_t res; //LOG("spe add\n"); if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) { cpu->CPSR.bits.Q=1; mul = 0x80000000-BIT31(mul); } 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 //----------------------------------------------------------------------------- #define HWORD(i) ((int32_t)(((int32_t)(i))>>16)) #define LWORD(i) (int32_t)(((int32_t)((i)<<16))>>16) TEMPLATE static uint32_t FASTCALL OP_SMUL_B_B(const uint32_t i) { // checked //INFO("SMUL_B_B\n"); cpu->R[REG_POS(i,16)] = (uint32_t)(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(const uint32_t i) { //INFO("SMUL_B_T\n"); cpu->R[REG_POS(i,16)] = (uint32_t)(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(const uint32_t i) { //INFO("SMUL_T_B\n"); cpu->R[REG_POS(i,16)] = (uint32_t)(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(const uint32_t i) { //INFO("SMUL_T_T\n"); cpu->R[REG_POS(i,16)] = (uint32_t)(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(const uint32_t i) { uint32_t tmp = (uint32_t)((int16_t)cpu->R[REG_POS(i,0)]* (int16_t)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; //INFO("SMLABB %08X * %08X + %08X = %08X\n", (int16_t)cpu->R[REG_POS(i,0)], (int16_t)cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,12)], (int32_t)cpu->R[REG_POS(i,16)]); return 2; } TEMPLATE static uint32_t FASTCALL OP_SMLA_B_T(const uint32_t i) { uint32_t tmp = (uint32_t)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); uint32_t a = cpu->R[REG_POS(i,12)]; //INFO("SMLABT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); 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(const uint32_t i) { uint32_t tmp = (uint32_t)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); uint32_t a = cpu->R[REG_POS(i,12)]; //INFO("SMLATB %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); 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(const uint32_t i) { uint32_t tmp = (uint32_t)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); uint32_t a = cpu->R[REG_POS(i,12)]; //INFO("SMLATT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); 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(const uint32_t i) { int64_t tmp = (int64_t)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); uint64_t res = (uint64_t)tmp + cpu->R[REG_POS(i,12)]; //INFO("SMLALBB %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(uint32_t) res); cpu->R[REG_POS(i,12)] = (uint32_t) res; cpu->R[REG_POS(i,16)] += static_cast(res + ((tmp<0)*0xFFFFFFFF)); return 2; } TEMPLATE static uint32_t FASTCALL OP_SMLAL_B_T(const uint32_t i) { int64_t tmp = (int64_t)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); uint64_t res = (uint64_t)tmp + cpu->R[REG_POS(i,12)]; //INFO("SMLALBT %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(uint32_t) res); cpu->R[REG_POS(i,12)] = (uint32_t) res; cpu->R[REG_POS(i,16)] += static_cast(res + ((tmp<0)*0xFFFFFFFF)); return 2; } TEMPLATE static uint32_t FASTCALL OP_SMLAL_T_B(const uint32_t i) { int64_t tmp = (int64_t)(HWORD(cpu->R[REG_POS(i,0)])* (int64_t)LWORD(cpu->R[REG_POS(i,8)])); uint64_t res = (uint64_t)tmp + cpu->R[REG_POS(i,12)]; //INFO("SMLALTB %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(uint32_t) res); cpu->R[REG_POS(i,12)] = (uint32_t) res; cpu->R[REG_POS(i,16)] += static_cast(res + ((tmp<0)*0xFFFFFFFF)); return 2; } TEMPLATE static uint32_t FASTCALL OP_SMLAL_T_T(const uint32_t i) { int64_t tmp = (int64_t)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); uint64_t res = (uint64_t)tmp + cpu->R[REG_POS(i,12)]; //INFO("SMLALTT %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(uint32_t) res); cpu->R[REG_POS(i,12)] = (uint32_t) res; cpu->R[REG_POS(i,16)] += static_cast(res + ((tmp<0)*0xFFFFFFFF)); return 2; } //----------------------------------------------------------------------------- // SMULW //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_SMULW_B(const uint32_t i) { int64_t tmp = (int64_t)LWORD(cpu->R[REG_POS(i,8)]) * (int64_t)((int32_t)cpu->R[REG_POS(i,0)]); //INFO("SMULWB %08X * %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); return 2; } TEMPLATE static uint32_t FASTCALL OP_SMULW_T(const uint32_t i) { int64_t tmp = (int64_t)HWORD(cpu->R[REG_POS(i,8)]) * (int64_t)((int32_t)cpu->R[REG_POS(i,0)]); //INFO("SMULWT %08X * %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); return 2; } //----------------------------------------------------------------------------- // SMLAW //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_SMLAW_B(const uint32_t i) { int64_t tmp = (int64_t)LWORD(cpu->R[REG_POS(i,8)]) * (int64_t)((int32_t)cpu->R[REG_POS(i,0)]); uint32_t a = cpu->R[REG_POS(i,12)]; //INFO("SMLAWB %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a); tmp = (tmp>>16); cpu->R[REG_POS(i,16)] = static_cast(tmp + a); if(SIGNED_OVERFLOW((uint32_t)tmp, a, cpu->R[REG_POS(i,16)])) cpu->CPSR.bits.Q = 1; return 2; } TEMPLATE static uint32_t FASTCALL OP_SMLAW_T(const uint32_t i) { int64_t tmp = (int64_t)HWORD(cpu->R[REG_POS(i,8)]) * (int64_t)((int32_t)cpu->R[REG_POS(i,0)]); uint32_t a = cpu->R[REG_POS(i,12)]; //INFO("SMLAWT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a); tmp = ((tmp>>16)&0xFFFFFFFF); cpu->R[REG_POS(i,16)] = static_cast(tmp + a); if(SIGNED_OVERFLOW((uint32_t)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 (cpu->LDTBit) \ { \ 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 (cpu->LDTBit) \ { \ 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 (cpu->LDTBit) \ { \ 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(const 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(const 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_LDREX(const uint32_t i) { 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); } TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSL_IMM_OFF(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const uint32_t i) { OP_LDR_W2(3, 5, IMM_OFF_12); } TEMPLATE static uint32_t FASTCALL OP_LDR_M_IMM_OFF_POSTIND(const uint32_t i) { OP_LDR_W2(3, 5, -IMM_OFF_12); } TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static uint32_t FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; OP_LDR_W2(3, 5, -shift_op); } //----------------------------------------------------------------------------- // LDRB //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_LDRB_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr);; return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSR_IMM_OFF(const 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(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr);; return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_P_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static uint32_t FASTCALL OP_LDRB_M_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (uint32_t)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // STR //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_STR_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STREX(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); cpu->R[REG_POS(i,12)] = 0; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSR_IMM_OFF(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSR_IMM_OFF(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_P_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // STRB //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_STRB_P_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_IMM_OFF(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSL_IMM_OFF(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSR_IMM_OFF(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSR_IMM_OFF(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ASR_IMM_OFF(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ROR_IMM_OFF(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_IMM_OFF_PREIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSL_IMM_OFF_PREIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSR_IMM_OFF_PREIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ASR_IMM_OFF_PREIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ROR_IMM_OFF_PREIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_IMM_OFF_POSTIND(const uint32_t i) { uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSL_IMM_OFF_POSTIND(const uint32_t i) { LSL_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_LSR_IMM_OFF_POSTIND(const uint32_t i) { LSR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ASR_IMM_OFF_POSTIND(const uint32_t i) { ASR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_P_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static uint32_t FASTCALL OP_STRB_M_ROR_IMM_OFF_POSTIND(const uint32_t i) { ROR_IMM; uint32_t adr = cpu->R[REG_POS(i,16)]; WRITE8(cpu->mem_if->data, adr, (uint8_t)cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,16)] = adr - shift_op; return MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // LDMIA / LDMIB / LDMDA / LDMDB //----------------------------------------------------------------------------- #define OP_L_IA(reg, adr) if(BIT##reg(i)) \ { \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ adr += 4; \ } #define OP_L_IB(reg, adr) if(BIT##reg(i)) \ { \ adr += 4; \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ } #define OP_L_DA(reg, adr) if(BIT##reg(i)) \ { \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ adr -= 4; \ } #define OP_L_DB(reg, adr) if(BIT##reg(i)) \ { \ adr -= 4; \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ } TEMPLATE static uint32_t FASTCALL OP_LDMIA(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres = cpu->R; OP_L_IA(0, start); OP_L_IA(1, start); OP_L_IA(2, start); OP_L_IA(3, start); OP_L_IA(4, start); OP_L_IA(5, start); OP_L_IA(6, start); OP_L_IA(7, start); OP_L_IA(8, start); OP_L_IA(9, start); OP_L_IA(10, start); OP_L_IA(11, start); OP_L_IA(12, start); OP_L_IA(13, start); OP_L_IA(14, start); if(BIT15(i)) { uint32_t tmp = READ32(cpu->mem_if->data, start); // TODO // The general-purpose registers loaded can include the PC. If they do, the word loaded for the PC is treated // as an address and a branch occurs to that address. In ARMv5 and above, bit[0] of the loaded value // determines whether execution continues after this branch in ARM state or in Thumb state, as though a BX // (loaded_value) instruction had been executed (but see also The T and J bits on page A2-15 for operation on // non-T variants of ARMv5). In earlier versions of the architecture, bits[1:0] of the loaded value are ignored // and execution continues in ARM state, as though the instruction MOV PC,(loaded_value) had been executed. // //value = Memory[address,4] //if (architecture version 5 or above) then // pc = value AND 0xFFFFFFFE // T Bit = value[0] //else // pc = value AND 0xFFFFFFFC if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; //start += 4; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIB(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres = cpu->R; OP_L_IB(0, start); OP_L_IB(1, start); OP_L_IB(2, start); OP_L_IB(3, start); OP_L_IB(4, start); OP_L_IB(5, start); OP_L_IB(6, start); OP_L_IB(7, start); OP_L_IB(8, start); OP_L_IB(9, start); OP_L_IB(10, start); OP_L_IB(11, start); OP_L_IB(12, start); OP_L_IB(13, start); OP_L_IB(14, start); if(BIT15(i)) { start += 4; c += MMU_memAccessCycles(start); uint32_t tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; return MMU_aluMemCycles(4, c); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDA(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres = cpu->R; if(BIT15(i)) { uint32_t tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); start -= 4; cpu->next_instruction = registres[15]; } OP_L_DA(14, start); OP_L_DA(13, start); OP_L_DA(12, start); OP_L_DA(11, start); OP_L_DA(10, start); OP_L_DA(9, start); OP_L_DA(8, start); OP_L_DA(7, start); OP_L_DA(6, start); OP_L_DA(5, start); OP_L_DA(4, start); OP_L_DA(3, start); OP_L_DA(2, start); OP_L_DA(1, start); OP_L_DA(0, start); return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDB(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres = cpu->R; if(BIT15(i)) { start -= 4; uint32_t tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } OP_L_DB(14, start); OP_L_DB(13, start); OP_L_DB(12, start); OP_L_DB(11, start); OP_L_DB(10, start); OP_L_DB(9, start); OP_L_DB(8, start); OP_L_DB(7, start); OP_L_DB(6, start); OP_L_DB(5, start); OP_L_DB(4, start); OP_L_DB(3, start); OP_L_DB(2, start); OP_L_DB(1, start); OP_L_DB(0, start); return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIA_W(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; uint32_t * registres = cpu->R; OP_L_IA(0, start); OP_L_IA(1, start); OP_L_IA(2, start); OP_L_IA(3, start); OP_L_IA(4, start); OP_L_IA(5, start); OP_L_IA(6, start); OP_L_IA(7, start); OP_L_IA(8, start); OP_L_IA(9, start); OP_L_IA(10, start); OP_L_IA(11, start); OP_L_IA(12, start); OP_L_IA(13, start); OP_L_IA(14, start); if(BIT15(i)) { uint32_t tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); start += 4; cpu->next_instruction = registres[15]; } if(i & (1 << REG_POS(i,16))) { if(i & bitList) cpu->R[REG_POS(i,16)] = start; } else cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIB_W(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; uint32_t * registres = cpu->R; OP_L_IB(0, start); OP_L_IB(1, start); OP_L_IB(2, start); OP_L_IB(3, start); OP_L_IB(4, start); OP_L_IB(5, start); OP_L_IB(6, start); OP_L_IB(7, start); OP_L_IB(8, start); OP_L_IB(9, start); OP_L_IB(10, start); OP_L_IB(11, start); OP_L_IB(12, start); OP_L_IB(13, start); OP_L_IB(14, start); if(BIT15(i)) { uint32_t tmp; start += 4; c += MMU_memAccessCycles(start); tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; } if(i & (1 << REG_POS(i,16))) { if(i & bitList) cpu->R[REG_POS(i,16)] = start; } else cpu->R[REG_POS(i,16)] = start; if(BIT15(i)) return MMU_aluMemCycles(4, c); else return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDA_W(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; uint32_t * registres = cpu->R; if(BIT15(i)) { uint32_t tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); start -= 4; cpu->next_instruction = registres[15]; } OP_L_DA(14, start); OP_L_DA(13, start); OP_L_DA(12, start); OP_L_DA(11, start); OP_L_DA(10, start); OP_L_DA(9, start); OP_L_DA(8, start); OP_L_DA(7, start); OP_L_DA(6, start); OP_L_DA(5, start); OP_L_DA(4, start); OP_L_DA(3, start); OP_L_DA(2, start); OP_L_DA(1, start); OP_L_DA(0, start); if(i & (1 << REG_POS(i,16))) { if(i & bitList) cpu->R[REG_POS(i,16)] = start; } else cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDB_W(const uint32_t i) { uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; uint32_t * registres = cpu->R; if(BIT15(i)) { uint32_t tmp; start -= 4; tmp = READ32(cpu->mem_if->data, start); if (cpu->LDTBit) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } OP_L_DB(14, start); OP_L_DB(13, start); OP_L_DB(12, start); OP_L_DB(11, start); OP_L_DB(10, start); OP_L_DB(9, start); OP_L_DB(8, start); OP_L_DB(7, start); OP_L_DB(6, start); OP_L_DB(5, start); OP_L_DB(4, start); OP_L_DB(3, start); OP_L_DB(2, start); OP_L_DB(1, start); OP_L_DB(0, start); if(i & (1 << REG_POS(i,16))) { if(i & bitList) cpu->R[REG_POS(i,16)] = start; } else cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIA2(const uint32_t i) { uint32_t oldmode = 0; uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; OP_L_IA(0, start); OP_L_IA(1, start); OP_L_IA(2, start); OP_L_IA(3, start); OP_L_IA(4, start); OP_L_IA(5, start); OP_L_IA(6, start); OP_L_IA(7, start); OP_L_IA(8, start); OP_L_IA(9, start); OP_L_IA(10, start); OP_L_IA(11, start); OP_L_IA(12, start); OP_L_IA(13, start); OP_L_IA(14, start); if(BIT15(i) == 0) { armcpu_switchMode(cpu, static_cast(oldmode)); } else { uint32_t tmp = READ32(cpu->mem_if->data, start); Status_Reg SPSR; cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); //start += 4; cpu->next_instruction = cpu->R[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIB2(const uint32_t i) { uint32_t oldmode = 0; uint32_t c = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; //UNTESTEDOPCODELOG("Untested opcode: OP_LDMIB2 \n"); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; OP_L_IB(0, start); OP_L_IB(1, start); OP_L_IB(2, start); OP_L_IB(3, start); OP_L_IB(4, start); OP_L_IB(5, start); OP_L_IB(6, start); OP_L_IB(7, start); OP_L_IB(8, start); OP_L_IB(9, start); OP_L_IB(10, start); OP_L_IB(11, start); OP_L_IB(12, start); OP_L_IB(13, start); OP_L_IB(14, start); if(BIT15(i) == 0) { armcpu_switchMode(cpu, static_cast(oldmode)); } else { uint32_t tmp; Status_Reg SPSR; start += 4; tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDA2(const uint32_t i) { uint32_t oldmode = 0; uint32_t c = 0; uint32_t * registres; uint32_t start = cpu->R[REG_POS(i,16)]; //UNTESTEDOPCODELOG("Untested opcode: OP_LDMDA2 \n"); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { uint32_t tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); c += MMU_memAccessCycles(start); start -= 4; cpu->next_instruction = registres[15]; } OP_L_DA(14, start); OP_L_DA(13, start); OP_L_DA(12, start); OP_L_DA(11, start); OP_L_DA(10, start); OP_L_DA(9, start); OP_L_DA(8, start); OP_L_DA(7, start); OP_L_DA(6, start); OP_L_DA(5, start); OP_L_DA(4, start); OP_L_DA(3, start); OP_L_DA(2, start); OP_L_DA(1, start); OP_L_DA(0, start); if(BIT15(i)==0) { armcpu_switchMode(cpu, static_cast(oldmode)); } else { Status_Reg SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDB2(const uint32_t i) { uint32_t oldmode = 0; uint32_t c = 0; uint32_t * registres; uint32_t start = cpu->R[REG_POS(i,16)]; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { uint32_t tmp; start -= 4; tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } OP_L_DB(14, start); OP_L_DB(13, start); OP_L_DB(12, start); OP_L_DB(11, start); OP_L_DB(10, start); OP_L_DB(9, start); OP_L_DB(8, start); OP_L_DB(7, start); OP_L_DB(6, start); OP_L_DB(5, start); OP_L_DB(4, start); OP_L_DB(3, start); OP_L_DB(2, start); OP_L_DB(1, start); OP_L_DB(0, start); if(BIT15(i)==0) { armcpu_switchMode(cpu, static_cast(oldmode)); } else { Status_Reg SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIA2_W(const uint32_t i) { uint32_t c = 0; uint32_t oldmode = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; uint32_t tmp; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; OP_L_IA(0, start); OP_L_IA(1, start); OP_L_IA(2, start); OP_L_IA(3, start); OP_L_IA(4, start); OP_L_IA(5, start); OP_L_IA(6, start); OP_L_IA(7, start); OP_L_IA(8, start); OP_L_IA(9, start); OP_L_IA(10, start); OP_L_IA(11, start); OP_L_IA(12, start); OP_L_IA(13, start); OP_L_IA(14, start); if(BIT15(i)==0) { if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(2, c); } if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start + 4; tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMIB2_W(const uint32_t i) { uint32_t c = 0; uint32_t oldmode = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; uint32_t tmp; Status_Reg SPSR; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; OP_L_IB(0, start); OP_L_IB(1, start); OP_L_IB(2, start); OP_L_IB(3, start); OP_L_IB(4, start); OP_L_IB(5, start); OP_L_IB(6, start); OP_L_IB(7, start); OP_L_IB(8, start); OP_L_IB(9, start); OP_L_IB(10, start); OP_L_IB(11, start); OP_L_IB(12, start); OP_L_IB(13, start); OP_L_IB(14, start); if(BIT15(i)==0) { if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(2, c); } if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start + 4; tmp = READ32(cpu->mem_if->data, start + 4); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); cpu->next_instruction = registres[15]; SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); c += MMU_memAccessCycles(start); return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDA2_W(const uint32_t i) { uint32_t c = 0; uint32_t oldmode = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { if (BIT_N(i, REG_POS(i,16))) printf("error1_1\n"); uint32_t tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); c += MMU_memAccessCycles(start); start -= 4; cpu->next_instruction = registres[15]; } OP_L_DA(14, start); OP_L_DA(13, start); OP_L_DA(12, start); OP_L_DA(11, start); OP_L_DA(10, start); OP_L_DA(9, start); OP_L_DA(8, start); OP_L_DA(7, start); OP_L_DA(6, start); OP_L_DA(5, start); OP_L_DA(4, start); OP_L_DA(3, start); OP_L_DA(2, start); OP_L_DA(1, start); OP_L_DA(0, start); if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; if(BIT15(i)==0) { armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(2, c); } SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } TEMPLATE static uint32_t FASTCALL OP_LDMDB2_W(const uint32_t i) { uint32_t c = 0; uint32_t oldmode = 0; uint32_t start = cpu->R[REG_POS(i,16)]; uint32_t * registres; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { if (BIT_N(i, REG_POS(i,16))) printf("error1_2\n"); uint32_t tmp; start -= 4; tmp = READ32(cpu->mem_if->data, start); c += MMU_memAccessCycles(start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); cpu->next_instruction = registres[15]; } OP_L_DB(14, start); OP_L_DB(13, start); OP_L_DB(12, start); OP_L_DB(11, start); OP_L_DB(10, start); OP_L_DB(9, start); OP_L_DB(8, start); OP_L_DB(7, start); OP_L_DB(6, start); OP_L_DB(5, start); OP_L_DB(4, start); OP_L_DB(3, start); OP_L_DB(2, start); OP_L_DB(1, start); OP_L_DB(0, start); if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; if(BIT15(i)==0) { armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(2, c); } SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } //----------------------------------------------------------------------------- // STMIA / STMIB / STMDA / STMDB //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_STMIA(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIB(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, b)) { start += 4; WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); } } return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDA(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDB(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { start -= 4; WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); } } return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIA_W(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIB_W(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, b)) { start += 4; WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDA_W(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDB_W(const uint32_t i) { uint32_t c = 0, b; uint32_t start = cpu->R[REG_POS(i,16)]; for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { start -= 4; WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIA2(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIB2(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMIB2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { start += 4; WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); } } armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDA2(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDB2(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c=0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { start -= 4; WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); } } armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIA2_W(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c=0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2_W \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMIB2_W(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c=0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); for(b=0; b<16; b++) { if(BIT_N(i, b)) { start += 4; WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); } } armcpu_switchMode(cpu, static_cast(oldmode)); cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDA2_W(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2_W \n"); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } TEMPLATE static uint32_t FASTCALL OP_STMDB2_W(const uint32_t i) { uint32_t c, b; uint32_t start; uint32_t oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); //UNTESTEDOPCODELOG("Untested opcode: OP_STMDB2_W \n"); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { start -= 4; WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, static_cast(oldmode)); return MMU_aluMemCycles(1, c); } //----------------------------------------------------------------------------- // LDRD / STRD //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_LDRD_STRD_POST_INDEX(const uint32_t i) { uint32_t Rd_num = REG_POS( i, 12); uint32_t addr = cpu->R[REG_POS(i,16)]; uint32_t index; //printf("%s POST\n", BIT5(i)?"STRD":"LDRD"); /* I bit - immediate or register */ if ( BIT22(i)) index = IMM_OFF; else index = cpu->R[REG_POS(i,0)]; // U bit - add or subtract if ( BIT23(i)) cpu->R[REG_POS(i,16)] += index; else cpu->R[REG_POS(i,16)] -= index; uint32_t c = 0; if ( !(Rd_num & 0x1)) { // Store/Load if ( BIT5(i)) { WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } else { cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } } return MMU_aluMemCycles(3, c); } TEMPLATE static uint32_t FASTCALL OP_LDRD_STRD_OFFSET_PRE_INDEX(const uint32_t i) { uint32_t Rd_num = REG_POS( i, 12); uint32_t addr = cpu->R[REG_POS(i,16)]; uint32_t index; //printf("%s PRE\n", BIT5(i)?"STRD":"LDRD"); // I bit - immediate or register if ( BIT22(i)) index = IMM_OFF; else index = cpu->R[REG_POS(i,0)]; // U bit - add or subtract if ( BIT23(i)) addr += index; else addr -= index; uint32_t c = 0; if ( !(Rd_num & 0x1)) { // Store/Load if ( BIT5(i)) { WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); // W bit - writeback if ( BIT21(i)) cpu->R[REG_POS(i,16)] = addr; } else { // W bit - writeback if ( BIT21(i)) cpu->R[REG_POS(i,16)] = addr; cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } } return MMU_aluMemCycles(3, c); } //----------------------------------------------------------------------------- // STC // the NDS has no coproc that responses to a STC, no feedback is given to the arm //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_STC_P_IMM_OFF(const uint32_t) { //INFO("OP_STC_P_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_M_IMM_OFF(const uint32_t) { //INFO("OP_STC_M_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_P_PREIND(const uint32_t) { //INFO("OP_STC_P_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_M_PREIND(const uint32_t) { //INFO("OP_STC_M_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_P_POSTIND(const uint32_t) { //INFO("OP_STC_P_POSTIND: cp_num %i\n", (i>>8)&0x0F); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_M_POSTIND(const uint32_t) { //INFO("OP_STC_M_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_STC_OPTION(const uint32_t) { //INFO("OP_STC_OPTION\n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // LDC // the NDS has no coproc that responses to a LDC, no feedback is given to the arm //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_LDC_P_IMM_OFF(const uint32_t) { //INFO("OP_LDC_P_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_M_IMM_OFF(const uint32_t) { //INFO("OP_LDC_M_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_P_PREIND(const uint32_t) { //INFO("OP_LDC_P_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_M_PREIND(const uint32_t) { //INFO("OP_LDC_M_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_P_POSTIND(const uint32_t) { //INFO("OP_LDC_P_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_M_POSTIND(const uint32_t) { //INFO("OP_LDC_M_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static uint32_t FASTCALL OP_LDC_OPTION(const uint32_t) { //INFO("OP_LDC_OPTION\n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // MCR / MRC //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_MCR(const uint32_t i) { uint32_t cpnum = REG_POS(i, 8); if(!cpu->coproc[cpnum]) { //emu_halt(); //INFO("Stopped (OP_MCR) \n"); /*INFO("ARM%c: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);*/ return 2; } armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], static_cast(REG_POS(i, 16)), static_cast(REG_POS(i, 0)), (i>>21)&0x7, (i>>5)&0x7); //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); return 2; } TEMPLATE static uint32_t FASTCALL OP_MRC(const uint32_t i) { //if (PROCNUM != 0) return 1; uint32_t cpnum = REG_POS(i, 8); if(!cpu->coproc[cpnum]) { //emu_halt(); //INFO("Stopped (OP_MRC) \n"); /*INFO("ARM%c: MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);*/ return 2; } // ARM REF: //data = value from Coprocessor[cp_num] //if Rd is R15 then // N flag = data[31] // Z flag = data[30] // C flag = data[29] // V flag = data[28] //else /* Rd is not R15 */ // Rd = data uint32_t data = 0; armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &data, static_cast(REG_POS(i, 16)), static_cast(REG_POS(i, 0)), (i>>21)&0x7, (i>>5)&0x7); if (REG_POS(i, 12) == 15) { cpu->CPSR.bits.N = BIT31(data); cpu->CPSR.bits.Z = BIT30(data); cpu->CPSR.bits.C = BIT29(data); cpu->CPSR.bits.V = BIT28(data); } else cpu->R[REG_POS(i, 12)] = data; //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); return 4; } //----------------------------------------------------------------------------- // SWI //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_SWI(const uint32_t i) { uint32_t swinum = (i>>16)&0xFF; //ideas-style debug prints (execute this SWI with the null terminated string address in R0) if(swinum==0xFC) { //IdeasLog(cpu); return 0; } //if the user has changed the intVector to point away from the nds bioses, //then it doesn't really make any sense to use the builtin SWI's since //the bios ones aren't getting called anyway bool bypassBuiltinSWI = (cpu->intVector == 0x00000000 && PROCNUM==0) || (cpu->intVector == 0xFFFF0000 && PROCNUM==1); if(cpu->swi_tab && !bypassBuiltinSWI) { swinum &= 0x1F; //printf("%d ARM SWI %d \n",PROCNUM,swinum); return cpu->swi_tab[swinum]() + 3; } else { /* TODO (#1#): translocated SWI vectors */ /* we use an irq thats not in the irq tab, as it was replaced duie to a changed intVector */ Status_Reg tmp = cpu->CPSR; armcpu_switchMode(cpu, SVC); /* enter svc mode */ cpu->R[14] = cpu->next_instruction; cpu->SPSR = tmp; /* save old CPSR as new SPSR */ cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ cpu->CPSR.bits.I = 1; cpu->changeCPSR(); cpu->R[15] = cpu->intVector + 0x08; cpu->next_instruction = cpu->R[15]; return 4; } } //----------------------------------------------------------------------------- // BKPT //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_BKPT(const uint32_t i) { static uint32_t last_bkpt = 0xFFFFFFFF; if(i != last_bkpt) printf("ARM OP_BKPT triggered\n"); last_bkpt = i; //this is not 100% correctly emulated, but it does the job cpu->next_instruction = cpu->instruct_adr; return 4; } //----------------------------------------------------------------------------- // CDP //----------------------------------------------------------------------------- TEMPLATE static uint32_t FASTCALL OP_CDP(const uint32_t) { //INFO("Stopped (OP_CDP) \n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // The End //----------------------------------------------------------------------------- #define TABDECL(x) x<0> const ArmOpFunc arm_instructions_set_0[4096] = { #include "instruction_tabdef.inc" }; #undef TABDECL #define TABDECL(x) x<1> const ArmOpFunc arm_instructions_set_1[4096] = { #include "instruction_tabdef.inc" }; #undef TABDECL /*#define TABDECL(x) #x const char* arm_instruction_names[4096] = { #include "instruction_tabdef.inc" }; #undef TABDECL*/