2016-12-05 17:02:29 +00:00
/*
2024-06-15 15:01:19 +00:00
Copyright 2016 - 2024 melonDS team
2016-12-05 17:02:29 +00:00
This file is part of melonDS .
melonDS 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 3 of the License , or ( at your option )
any later version .
melonDS 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 melonDS . If not , see http : //www.gnu.org/licenses/.
*/
2016-12-03 16:58:24 +00:00
# include <stdio.h>
2016-12-03 00:31:33 +00:00
# include "ARM.h"
2023-11-25 17:32:09 +00:00
namespace melonDS : : ARMInterpreter
2016-12-03 00:31:33 +00:00
{
// copypasta from ALU. bad
# define LSL_IMM(x, s) \
x < < = s ;
# define LSR_IMM(x, s) \
2016-12-23 20:22:22 +00:00
if ( s = = 0 ) x = 0 ; \
else x > > = s ;
2016-12-03 00:31:33 +00:00
# define ASR_IMM(x, s) \
2016-12-23 20:22:22 +00:00
if ( s = = 0 ) x = ( ( s32 ) x ) > > 31 ; \
else x = ( ( s32 ) x ) > > s ;
2016-12-03 00:31:33 +00:00
# define ROR_IMM(x, s) \
if ( s = = 0 ) \
{ \
x = ( x > > 1 ) | ( ( cpu - > CPSR & 0x20000000 ) < < 2 ) ; \
} \
else \
{ \
x = ROR ( x , s ) ; \
}
# define A_WB_CALC_OFFSET_IMM \
u32 offset = ( cpu - > CurInstr & 0xFFF ) ; \
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) ) offset = - offset ;
# define A_WB_CALC_OFFSET_REG(shiftop) \
2024-07-12 00:06:56 +00:00
u32 offset = cpu - > R [ cpu - > CurInstr & 0xF ] ; \
2016-12-03 00:31:33 +00:00
u32 shift = ( ( cpu - > CurInstr > > 7 ) & 0x1F ) ; \
shiftop ( offset , shift ) ; \
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) ) offset = - offset ;
2024-08-23 23:13:17 +00:00
enum class Writeback
{
None = 0 ,
Pre ,
Post ,
2024-08-27 00:43:27 +00:00
Trans ,
2024-08-23 23:13:17 +00:00
} ;
template < bool signror , int size , Writeback writeback >
void LoadSingle ( ARM * cpu , u8 rd , u8 rn , s32 offset )
{
static_assert ( ( size = = 8 ) | | ( size = = 16 ) | | ( size = = 32 ) , " dummy this function only takes 8/16/32 for size!!! " ) ;
u32 addr ;
2024-08-27 00:43:27 +00:00
if constexpr ( writeback < Writeback : : Post ) addr = offset + cpu - > R [ rn ] ;
2024-08-23 23:13:17 +00:00
else addr = cpu - > R [ rn ] ;
2024-08-27 00:43:27 +00:00
if constexpr ( writeback = = Writeback : : Trans )
{
if ( cpu - > Num = = 0 )
( ( ARMv5 * ) cpu ) - > PU_Map = ( ( ARMv5 * ) cpu ) - > PU_UserMap ;
}
2024-08-23 23:13:17 +00:00
u32 val ;
bool dataabort ;
if constexpr ( size = = 8 ) dataabort = ! cpu - > DataRead8 ( addr , & val ) ;
if constexpr ( size = = 16 ) dataabort = ! cpu - > DataRead16 ( addr , & val ) ;
if constexpr ( size = = 32 ) dataabort = ! cpu - > DataRead32 ( addr , & val ) ;
2024-08-27 00:43:27 +00:00
if constexpr ( writeback = = Writeback : : Trans )
{
if ( cpu - > Num = = 0 & & ( cpu - > CPSR & 0x1F ) ! = 0x10 )
( ( ARMv5 * ) cpu ) - > PU_Map = ( ( ARMv5 * ) cpu ) - > PU_PrivMap ;
}
2024-08-23 23:13:17 +00:00
cpu - > AddCycles_CDI ( ) ;
if ( dataabort ) return ;
if constexpr ( size = = 8 & & signror ) val = ( s32 ) ( s8 ) val ;
if constexpr ( size = = 16 & & signror ) val = ( s32 ) ( s16 ) val ;
if constexpr ( size = = 32 & & signror ) val = ROR ( val , ( ( addr & 0x3 ) < < 3 ) ) ;
if constexpr ( writeback ! = Writeback : : None ) cpu - > R [ rn ] + = offset ;
if ( rd = = 15 )
{
if ( cpu - > Num = = 1 | | ( ( ( ARMv5 * ) cpu ) - > CP15Control & ( 1 < < 15 ) ) ) val & = ~ 0x1 ;
cpu - > JumpTo ( val ) ;
}
else cpu - > R [ rd ] = val ;
}
template < int size , Writeback writeback >
void StoreSingle ( ARM * cpu , u8 rd , u8 rn , s32 offset )
{
static_assert ( ( size = = 8 ) | | ( size = = 16 ) | | ( size = = 32 ) , " dummy this function only takes 8/16/32 for size!!! " ) ;
u32 addr ;
2024-08-28 17:45:46 +00:00
if constexpr ( writeback < Writeback : : Post ) addr = offset + cpu - > R [ rn ] ;
2024-08-23 23:13:17 +00:00
else addr = cpu - > R [ rn ] ;
u32 storeval = cpu - > R [ rd ] ;
if ( rd = = 15 ) storeval + = 4 ;
2024-08-28 17:45:46 +00:00
if constexpr ( writeback = = Writeback : : Trans )
{
if ( cpu - > Num = = 0 )
( ( ARMv5 * ) cpu ) - > PU_Map = ( ( ARMv5 * ) cpu ) - > PU_UserMap ;
}
2024-08-23 23:13:17 +00:00
bool dataabort ;
if constexpr ( size = = 8 ) dataabort = ! cpu - > DataWrite8 ( addr , storeval ) ;
if constexpr ( size = = 16 ) dataabort = ! cpu - > DataWrite16 ( addr , storeval ) ;
if constexpr ( size = = 32 ) dataabort = ! cpu - > DataWrite32 ( addr , storeval ) ;
2024-08-28 17:45:46 +00:00
if constexpr ( writeback = = Writeback : : Trans )
{
if ( cpu - > Num = = 0 & & ( cpu - > CPSR & 0x1F ) ! = 0x10 )
( ( ARMv5 * ) cpu ) - > PU_Map = ( ( ARMv5 * ) cpu ) - > PU_PrivMap ;
}
2024-08-23 23:13:17 +00:00
cpu - > AddCycles_CD ( ) ;
if ( dataabort ) return ;
if constexpr ( writeback ! = Writeback : : None ) cpu - > R [ rn ] + = offset ;
}
2016-12-03 00:31:33 +00:00
# define A_STR \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) StoreSingle < 32 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else StoreSingle < 32 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_STR_POST \
2024-08-27 00:43:27 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) StoreSingle < 32 , Writeback : : Trans > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else StoreSingle < 32 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_STRB \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) StoreSingle < 8 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else StoreSingle < 8 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_STRB_POST \
2024-08-27 00:43:27 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) StoreSingle < 8 , Writeback : : Trans > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else StoreSingle < 8 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_LDR \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < true , 32 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < true , 32 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_LDR_POST \
2024-08-27 00:43:27 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < true , 32 , Writeback : : Trans > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < true , 32 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_LDRB \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < false , 8 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < false , 8 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_LDRB_POST \
2024-08-27 00:43:27 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < false , 8 , Writeback : : Trans > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < false , 8 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 00:31:33 +00:00
# define A_IMPLEMENT_WB_LDRSTR(x) \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _IMM ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_IMM \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _REG_LSL ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( LSL_IMM ) \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _REG_LSR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( LSR_IMM ) \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _REG_ASR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( ASR_IMM ) \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _REG_ROR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( ROR_IMM ) \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_IMM ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_IMM \
A_ # # x # # _POST \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_REG_LSL ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( LSL_IMM ) \
A_ # # x # # _POST \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_REG_LSR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( LSR_IMM ) \
A_ # # x # # _POST \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_REG_ASR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( ASR_IMM ) \
A_ # # x # # _POST \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_REG_ROR ( ARM * cpu ) \
2016-12-03 00:31:33 +00:00
{ \
A_WB_CALC_OFFSET_REG ( ROR_IMM ) \
A_ # # x # # _POST \
}
A_IMPLEMENT_WB_LDRSTR ( STR )
A_IMPLEMENT_WB_LDRSTR ( STRB )
A_IMPLEMENT_WB_LDRSTR ( LDR )
A_IMPLEMENT_WB_LDRSTR ( LDRB )
# define A_HD_CALC_OFFSET_IMM \
u32 offset = ( cpu - > CurInstr & 0xF ) | ( ( cpu - > CurInstr > > 4 ) & 0xF0 ) ; \
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) ) offset = - offset ;
# define A_HD_CALC_OFFSET_REG \
2024-07-12 00:06:56 +00:00
u32 offset = cpu - > R [ cpu - > CurInstr & 0xF ] ; \
2016-12-03 00:31:33 +00:00
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) ) offset = - offset ;
# define A_STRH \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) StoreSingle < 16 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else StoreSingle < 16 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_STRH_POST \
2024-08-23 23:13:17 +00:00
StoreSingle < 16 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
2017-06-13 13:09:39 +00:00
// TODO: CHECK LDRD/STRD TIMINGS!!
2016-12-03 03:05:23 +00:00
# define A_LDRD \
2017-06-13 15:44:35 +00:00
if ( cpu - > Num ! = 0 ) return ; \
2024-07-12 00:06:56 +00:00
offset + = cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] ; \
2016-12-03 03:05:23 +00:00
u32 r = ( cpu - > CurInstr > > 12 ) & 0xF ; \
2024-06-10 17:10:42 +00:00
if ( r & 1 ) { A_UNK ( cpu ) ; return ; } \
2024-08-04 18:45:28 +00:00
if ( ! cpu - > DataRead32 ( offset , & cpu - > R [ r ] ) ) { cpu - > AddCycles_CDI ( ) ; return ; } \
u32 val ; if ( ! cpu - > DataRead32S ( offset + 4 , & val ) ) { cpu - > AddCycles_CDI ( ) ; return ; } \
2024-07-12 00:06:56 +00:00
if ( r = = 14 ) cpu - > JumpTo ( ( ( ( ( ARMv5 * ) cpu ) - > CP15Control & ( 1 < < 15 ) ) ? ( val & ~ 0x1 ) : val ) , cpu - > CurInstr & ( 1 < < 22 ) ) ; /* restores cpsr presumably due to shared dna with ldm */ \
else cpu - > R [ r + 1 ] = val ; \
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ; \
2024-07-12 00:06:56 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] = offset ;
2016-12-03 03:05:23 +00:00
# define A_LDRD_POST \
2017-06-13 15:44:35 +00:00
if ( cpu - > Num ! = 0 ) return ; \
2024-07-12 00:06:56 +00:00
u32 addr = cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] ; \
2016-12-03 03:05:23 +00:00
u32 r = ( cpu - > CurInstr > > 12 ) & 0xF ; \
2024-06-10 17:10:42 +00:00
if ( r & 1 ) { A_UNK ( cpu ) ; return ; } \
2024-08-04 18:45:28 +00:00
if ( ! cpu - > DataRead32 ( addr , & cpu - > R [ r ] ) ) { cpu - > AddCycles_CDI ( ) ; return ; } \
u32 val ; if ( ! cpu - > DataRead32S ( addr + 4 , & val ) ) { cpu - > AddCycles_CDI ( ) ; return ; } \
2024-07-12 00:06:56 +00:00
if ( r = = 14 ) cpu - > JumpTo ( ( ( ( ( ARMv5 * ) cpu ) - > CP15Control & ( 1 < < 15 ) ) ? ( val & ~ 0x1 ) : val ) , cpu - > CurInstr & ( 1 < < 22 ) ) ; /* restores cpsr presumably due to shared dna with ldm */ \
else cpu - > R [ r + 1 ] = val ; \
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ; \
2024-06-05 01:22:39 +00:00
cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] + = offset ;
2016-12-03 03:05:23 +00:00
# define A_STRD \
2017-06-13 15:44:35 +00:00
if ( cpu - > Num ! = 0 ) return ; \
2024-07-12 00:06:56 +00:00
offset + = cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] ; \
2016-12-03 03:05:23 +00:00
u32 r = ( cpu - > CurInstr > > 12 ) & 0xF ; \
2024-06-10 17:10:42 +00:00
if ( r & 1 ) { A_UNK ( cpu ) ; return ; } \
2024-07-12 00:06:56 +00:00
bool dataabort = ! cpu - > DataWrite32 ( offset , cpu - > R [ r ] ) ; /* yes, this data abort behavior is on purpose */ \
u32 storeval = cpu - > R [ r + 1 ] ; if ( r = = 14 ) storeval + = 4 ; \
2024-06-08 03:46:49 +00:00
dataabort | = ! cpu - > DataWrite32S ( offset + 4 , storeval , dataabort ) ; /* no, i dont understand it either */ \
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CD ( ) ; \
2024-06-05 01:22:39 +00:00
if ( dataabort ) return ; \
if ( cpu - > CurInstr & ( 1 < < 21 ) ) cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] = offset ;
2016-12-03 03:05:23 +00:00
# define A_STRD_POST \
2017-06-13 15:44:35 +00:00
if ( cpu - > Num ! = 0 ) return ; \
2024-07-12 00:06:56 +00:00
u32 addr = cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] ; \
2016-12-03 03:05:23 +00:00
u32 r = ( cpu - > CurInstr > > 12 ) & 0xF ; \
2024-06-10 17:10:42 +00:00
if ( r & 1 ) { A_UNK ( cpu ) ; return ; } \
2024-07-12 00:06:56 +00:00
bool dataabort = ! cpu - > DataWrite32 ( addr , cpu - > R [ r ] ) ; \
u32 storeval = cpu - > R [ r + 1 ] ; if ( r = = 14 ) storeval + = 4 ; \
2024-06-08 03:46:49 +00:00
dataabort | = ! cpu - > DataWrite32S ( addr + 4 , storeval , dataabort ) ; \
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CD ( ) ; \
2024-06-05 01:22:39 +00:00
if ( dataabort ) return ; \
cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] + = offset ;
2016-12-03 03:05:23 +00:00
# define A_LDRH \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < false , 16 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < false , 16 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_LDRH_POST \
2024-08-23 23:13:17 +00:00
LoadSingle < false , 16 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_LDRSB \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < true , 8 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < true , 8 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_LDRSB_POST \
2024-08-23 23:13:17 +00:00
LoadSingle < true , 8 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_LDRSH \
2024-08-23 23:13:17 +00:00
if ( cpu - > CurInstr & ( 1 < < 21 ) ) LoadSingle < true , 16 , Writeback : : Pre > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ; \
else LoadSingle < true , 16 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_LDRSH_POST \
2024-08-23 23:13:17 +00:00
LoadSingle < true , 16 , Writeback : : Post > ( cpu , ( ( cpu - > CurInstr > > 12 ) & 0xF ) , ( ( cpu - > CurInstr > > 16 ) & 0xF ) , offset ) ;
2016-12-03 03:05:23 +00:00
# define A_IMPLEMENT_HD_LDRSTR(x) \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _IMM ( ARM * cpu ) \
2016-12-03 03:05:23 +00:00
{ \
A_HD_CALC_OFFSET_IMM \
A_ # # x \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _REG ( ARM * cpu ) \
2016-12-03 03:05:23 +00:00
{ \
A_HD_CALC_OFFSET_REG \
A_ # # x \
} \
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_IMM ( ARM * cpu ) \
2016-12-03 03:05:23 +00:00
{ \
A_HD_CALC_OFFSET_IMM \
A_ # # x # # _POST \
} \
\
2017-01-30 17:36:11 +00:00
void A_ # # x # # _POST_REG ( ARM * cpu ) \
2016-12-03 03:05:23 +00:00
{ \
A_HD_CALC_OFFSET_REG \
A_ # # x # # _POST \
}
A_IMPLEMENT_HD_LDRSTR ( STRH )
A_IMPLEMENT_HD_LDRSTR ( LDRD )
A_IMPLEMENT_HD_LDRSTR ( STRD )
A_IMPLEMENT_HD_LDRSTR ( LDRH )
A_IMPLEMENT_HD_LDRSTR ( LDRSB )
A_IMPLEMENT_HD_LDRSTR ( LDRSH )
2024-08-27 21:23:18 +00:00
template < bool byte >
inline void SWP ( ARM * cpu )
2016-12-05 16:08:24 +00:00
{
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ ( cpu - > CurInstr > > 16 ) & 0xF ] ;
u32 rm = cpu - > R [ cpu - > CurInstr & 0xF ] ;
2024-06-08 03:46:49 +00:00
if ( ( cpu - > CurInstr & 0xF ) = = 15 ) rm + = 4 ;
2016-12-05 16:08:24 +00:00
2018-12-04 16:54:10 +00:00
u32 val ;
2024-08-27 21:23:18 +00:00
if ( ( byte ? cpu - > DataRead8 ( base , & val )
: cpu - > DataRead32 ( base , & val ) ) )
2024-06-05 18:31:44 +00:00
{
u32 numD = cpu - > DataCycles ;
2024-08-27 21:23:18 +00:00
if ( ( byte ? cpu - > DataWrite8 ( base , rm )
: cpu - > DataWrite32 ( base , rm ) ) )
2024-06-05 18:31:44 +00:00
{
2024-06-10 22:03:56 +00:00
// rd only gets updated if both read and write succeed
2024-06-08 14:40:23 +00:00
u32 rd = ( cpu - > CurInstr > > 12 ) & 0xF ;
2024-08-27 21:23:18 +00:00
if constexpr ( ! byte ) val = ROR ( val , 8 * ( base & 0x3 ) ) ;
if ( rd ! = 15 ) cpu - > R [ rd ] = val ;
else if ( cpu - > Num = = 1 ) cpu - > JumpTo ( val & ~ 1 ) ; // for some reason these jumps don't seem to work on the arm 9?
2024-06-05 18:31:44 +00:00
}
2024-08-27 21:23:18 +00:00
2024-06-05 18:31:44 +00:00
cpu - > DataCycles + = numD ;
}
2024-08-27 21:23:18 +00:00
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ;
2016-12-05 16:08:24 +00:00
}
2024-08-27 21:23:18 +00:00
void A_SWP ( ARM * cpu )
2016-12-05 16:08:24 +00:00
{
2024-08-27 21:23:18 +00:00
void SWP < false > ( ARM * cpu ) ;
}
2016-12-05 16:08:24 +00:00
2024-08-27 21:23:18 +00:00
void A_SWPB ( ARM * cpu )
{
void SWP < true > ( ARM * cpu ) ;
2016-12-05 16:08:24 +00:00
}
2017-01-30 17:36:11 +00:00
void A_LDM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2016-12-23 20:22:22 +00:00
u32 baseid = ( cpu - > CurInstr > > 16 ) & 0xF ;
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ baseid ] ;
2016-12-23 20:22:22 +00:00
u32 wbbase ;
2024-06-02 14:13:50 +00:00
u32 oldbase = base ;
2016-12-03 16:58:24 +00:00
u32 preinc = ( cpu - > CurInstr & ( 1 < < 24 ) ) ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 16:58:24 +00:00
2024-06-02 14:13:50 +00:00
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) ) // decrement
2016-12-03 16:58:24 +00:00
{
2024-06-02 14:13:50 +00:00
// decrement is actually an increment starting from the end address
2016-12-03 16:58:24 +00:00
for ( int i = 0 ; i < 16 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
base - = 4 ;
}
if ( cpu - > CurInstr & ( 1 < < 21 ) )
{
2016-12-05 22:17:03 +00:00
// pre writeback
2016-12-23 20:22:22 +00:00
wbbase = base ;
2016-12-03 16:58:24 +00:00
}
preinc = ! preinc ;
}
2024-06-02 14:13:50 +00:00
// switch to user mode regs
2016-12-03 16:58:24 +00:00
if ( ( cpu - > CurInstr & ( 1 < < 22 ) ) & & ! ( cpu - > CurInstr & ( 1 < < 15 ) ) )
2021-10-28 19:15:12 +00:00
cpu - > UpdateMode ( cpu - > CPSR , ( cpu - > CPSR & ~ 0x1F ) | 0x10 , true ) ;
2016-12-03 16:58:24 +00:00
2024-06-02 14:13:50 +00:00
for ( int i = 0 ; i < 15 ; i + + )
2016-12-03 16:58:24 +00:00
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
if ( preinc ) base + = 4 ;
2024-06-02 23:34:29 +00:00
if ( ! ( first ? cpu - > DataRead32 ( base , & cpu - > R [ i ] )
: cpu - > DataRead32S ( base , & cpu - > R [ i ] ) ) )
{
2024-06-06 22:58:43 +00:00
goto dataabort ;
2024-06-02 23:34:29 +00:00
}
2018-12-09 00:17:05 +00:00
first = false ;
2024-06-15 20:07:36 +00:00
if ( ! preinc ) base + = 4 ;
2016-12-03 16:58:24 +00:00
}
}
2024-06-02 04:11:01 +00:00
2024-05-31 22:09:45 +00:00
u32 pc ;
2024-06-02 14:13:50 +00:00
if ( ( cpu - > CurInstr & ( 1 < < 15 ) ) )
2016-12-03 16:58:24 +00:00
{
if ( preinc ) base + = 4 ;
2024-06-02 23:34:29 +00:00
if ( ! ( first ? cpu - > DataRead32 ( base , & pc )
: cpu - > DataRead32S ( base , & pc ) ) )
{
2024-06-06 22:58:43 +00:00
goto dataabort ;
2024-06-02 23:34:29 +00:00
}
2016-12-03 16:58:24 +00:00
if ( ! preinc ) base + = 4 ;
2024-08-04 18:45:28 +00:00
if ( cpu - > Num = = 1 | | ( ( ( ARMv5 * ) cpu ) - > CP15Control & ( 1 < < 15 ) ) )
2016-12-03 16:58:24 +00:00
pc & = ~ 0x1 ;
}
2024-06-02 14:13:50 +00:00
// switch back to previous regs
2016-12-03 16:58:24 +00:00
if ( ( cpu - > CurInstr & ( 1 < < 22 ) ) & & ! ( cpu - > CurInstr & ( 1 < < 15 ) ) )
2021-10-28 19:15:12 +00:00
cpu - > UpdateMode ( ( cpu - > CPSR & ~ 0x1F ) | 0x10 , cpu - > CPSR , true ) ;
2016-12-03 16:58:24 +00:00
2024-06-06 22:58:43 +00:00
// writeback to base
if ( cpu - > CurInstr & ( 1 < < 21 ) )
2016-12-03 16:58:24 +00:00
{
2024-06-06 22:58:43 +00:00
// post writeback
if ( cpu - > CurInstr & ( 1 < < 23 ) )
wbbase = base ;
2024-06-02 04:11:01 +00:00
2024-06-06 22:58:43 +00:00
if ( cpu - > CurInstr & ( 1 < < baseid ) )
{
if ( cpu - > Num = = 0 )
2016-12-05 22:17:03 +00:00
{
2024-06-06 22:58:43 +00:00
u32 rlist = cpu - > CurInstr & 0xFFFF ;
if ( ( ! ( rlist & ~ ( 1 < < baseid ) ) ) | | ( rlist & ~ ( ( 2 < < baseid ) - 1 ) ) )
cpu - > R [ baseid ] = wbbase ;
2016-12-05 22:17:03 +00:00
}
}
2024-06-06 22:58:43 +00:00
else
cpu - > R [ baseid ] = wbbase ;
}
2024-06-02 14:13:50 +00:00
2024-06-06 22:58:43 +00:00
// jump if pc got written
if ( cpu - > CurInstr & ( 1 < < 15 ) )
cpu - > JumpTo ( pc , cpu - > CurInstr & ( 1 < < 22 ) ) ;
// jump here if a data abort occurred; writeback is ignored, and any jumps were aborted
if ( false )
{
dataabort :
// switch back to original set of regs
if ( ( cpu - > CurInstr & ( 1 < < 22 ) ) & & ! ( cpu - > CurInstr & ( 1 < < 15 ) ) )
cpu - > UpdateMode ( ( cpu - > CPSR & ~ 0x1F ) | 0x10 , cpu - > CPSR , true ) ;
// restore original value of base in case the reg got written to
cpu - > R [ baseid ] = oldbase ;
2024-06-02 04:11:01 +00:00
}
2024-07-12 00:06:56 +00:00
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ;
2016-12-03 16:58:24 +00:00
}
2017-01-30 17:36:11 +00:00
void A_STM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2016-12-23 20:22:22 +00:00
u32 baseid = ( cpu - > CurInstr > > 16 ) & 0xF ;
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ baseid ] ;
2016-12-23 20:22:22 +00:00
u32 oldbase = base ;
2016-12-03 16:58:24 +00:00
u32 preinc = ( cpu - > CurInstr & ( 1 < < 24 ) ) ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 16:58:24 +00:00
if ( ! ( cpu - > CurInstr & ( 1 < < 23 ) ) )
{
2017-01-30 17:36:11 +00:00
for ( u32 i = 0 ; i < 16 ; i + + )
2016-12-03 16:58:24 +00:00
{
if ( cpu - > CurInstr & ( 1 < < i ) )
base - = 4 ;
}
if ( cpu - > CurInstr & ( 1 < < 21 ) )
2016-12-23 20:22:22 +00:00
cpu - > R [ baseid ] = base ;
2016-12-03 16:58:24 +00:00
preinc = ! preinc ;
}
2017-02-05 15:50:20 +00:00
bool isbanked = false ;
2016-12-03 16:58:24 +00:00
if ( cpu - > CurInstr & ( 1 < < 22 ) )
2017-02-05 15:50:20 +00:00
{
u32 mode = ( cpu - > CPSR & 0x1F ) ;
if ( mode = = 0x11 )
isbanked = ( baseid > = 8 & & baseid < 15 ) ;
else if ( mode ! = 0x10 & & mode ! = 0x1F )
isbanked = ( baseid > = 13 & & baseid < 15 ) ;
2021-10-28 19:15:12 +00:00
cpu - > UpdateMode ( cpu - > CPSR , ( cpu - > CPSR & ~ 0x1F ) | 0x10 , true ) ;
2017-02-05 15:50:20 +00:00
}
2016-12-03 16:58:24 +00:00
2017-01-30 17:36:11 +00:00
for ( u32 i = 0 ; i < 16 ; i + + )
2016-12-03 16:58:24 +00:00
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
if ( preinc ) base + = 4 ;
2016-12-23 20:22:22 +00:00
2024-06-02 23:34:29 +00:00
u32 val ;
2017-02-05 15:50:20 +00:00
if ( i = = baseid & & ! isbanked )
2016-12-23 20:22:22 +00:00
{
2017-06-12 14:36:24 +00:00
if ( ( cpu - > Num = = 0 ) | | ( ! ( cpu - > CurInstr & ( ( 1 < < i ) - 1 ) ) ) )
2024-06-02 23:34:29 +00:00
val = oldbase ;
else val = base ;
}
2024-07-12 00:06:56 +00:00
else val = cpu - > R [ i ] ;
2024-06-02 23:34:29 +00:00
2024-06-08 03:46:49 +00:00
if ( i = = 15 ) val + = 4 ;
2024-06-02 23:34:29 +00:00
if ( ! ( first ? cpu - > DataWrite32 ( base , val )
: cpu - > DataWrite32S ( base , val ) ) )
{
2024-06-06 22:58:43 +00:00
goto dataabort ;
2016-12-23 20:22:22 +00:00
}
2018-12-04 16:54:10 +00:00
2018-12-09 00:17:05 +00:00
first = false ;
2016-12-23 20:22:22 +00:00
2016-12-03 16:58:24 +00:00
if ( ! preinc ) base + = 4 ;
}
}
if ( cpu - > CurInstr & ( 1 < < 22 ) )
2021-10-28 19:15:12 +00:00
cpu - > UpdateMode ( ( cpu - > CPSR & ~ 0x1F ) | 0x10 , cpu - > CPSR , true ) ;
2016-12-03 16:58:24 +00:00
2024-06-06 22:58:43 +00:00
if ( ( cpu - > CurInstr & ( 1 < < 23 ) ) & & ( cpu - > CurInstr & ( 1 < < 21 ) ) )
cpu - > R [ baseid ] = base ;
// jump here if a data abort occurred
if ( false )
2024-06-03 02:41:01 +00:00
{
2024-06-06 22:58:43 +00:00
dataabort :
if ( cpu - > CurInstr & ( 1 < < 22 ) )
cpu - > UpdateMode ( ( cpu - > CPSR & ~ 0x1F ) | 0x10 , cpu - > CPSR , true ) ;
// restore original value of base
cpu - > R [ baseid ] = oldbase ;
2024-06-03 02:41:01 +00:00
}
2018-12-04 16:54:10 +00:00
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CD ( ) ;
2016-12-03 16:58:24 +00:00
}
2016-12-03 03:05:23 +00:00
// ---- THUMB -----------------------
2024-07-12 00:06:56 +00:00
void T_LDR_PCREL ( ARM * cpu )
2016-12-03 03:05:23 +00:00
{
2024-06-17 22:07:53 +00:00
u32 addr = ( cpu - > R [ 15 ] & ~ 0x2 ) + ( ( cpu - > CurInstr & 0xFF ) < < 2 ) ;
2018-12-09 00:17:05 +00:00
cpu - > DataRead32 ( addr , & cpu - > R [ ( cpu - > CurInstr > > 8 ) & 0x7 ] ) ;
2016-12-03 03:05:23 +00:00
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ;
2016-12-03 03:05:23 +00:00
}
2024-07-12 00:06:56 +00:00
void T_STR_REG ( ARM * cpu )
2016-12-03 03:05:23 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 32 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 03:05:23 +00:00
}
2017-01-30 17:36:11 +00:00
void T_STRB_REG ( ARM * cpu )
2016-12-03 03:05:23 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 8 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 03:05:23 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDR_REG ( ARM * cpu )
2016-12-03 03:05:23 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < true , 32 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 03:05:23 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDRB_REG ( ARM * cpu )
2016-12-03 03:05:23 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < false , 8 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 03:05:23 +00:00
}
2016-12-03 00:31:33 +00:00
2017-01-30 17:36:11 +00:00
void T_STRH_REG ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 16 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 17:29:19 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDRSB_REG ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < true , 8 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 17:29:19 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDRH_REG ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < false , 16 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 17:29:19 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDRSH_REG ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < true , 16 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , cpu - > R [ ( cpu - > CurInstr > > 6 ) & 0x7 ] ) ;
2016-12-03 17:29:19 +00:00
}
2024-06-17 22:07:53 +00:00
void T_STR_IMM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 32 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 4 ) & 0x7C ) ) ;
2016-12-03 16:58:24 +00:00
}
2024-06-17 22:07:53 +00:00
void T_LDR_IMM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < true , 32 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 4 ) & 0x7C ) ) ;
2016-12-03 16:58:24 +00:00
}
2024-06-17 22:07:53 +00:00
void T_STRB_IMM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 8 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 6 ) & 0x1F ) ) ;
2016-12-03 16:58:24 +00:00
}
2024-06-17 22:07:53 +00:00
void T_LDRB_IMM ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < false , 8 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 6 ) & 0x1F ) ) ;
2016-12-03 16:58:24 +00:00
}
2024-06-17 22:07:53 +00:00
void T_STRH_IMM ( ARM * cpu )
2016-12-03 14:15:34 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 16 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 5 ) & 0x3E ) ) ;
2016-12-03 14:15:34 +00:00
}
2024-06-17 22:07:53 +00:00
void T_LDRH_IMM ( ARM * cpu )
2016-12-03 14:15:34 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < false , 16 , Writeback : : None > ( cpu , ( cpu - > CurInstr & 0x7 ) , ( ( cpu - > CurInstr > > 3 ) & 0x7 ) , ( ( cpu - > CurInstr > > 5 ) & 0x3E ) ) ;
2016-12-03 14:15:34 +00:00
}
2024-07-12 00:06:56 +00:00
void T_STR_SPREL ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
StoreSingle < 32 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 8 ) & 0x7 ) , 13 , ( ( cpu - > CurInstr < < 2 ) & 0x3FC ) ) ;
2016-12-03 16:58:24 +00:00
}
2024-07-12 00:06:56 +00:00
void T_LDR_SPREL ( ARM * cpu )
2016-12-03 16:58:24 +00:00
{
2024-08-23 23:13:17 +00:00
LoadSingle < false , 32 , Writeback : : None > ( cpu , ( ( cpu - > CurInstr > > 8 ) & 0x7 ) , 13 , ( ( cpu - > CurInstr < < 2 ) & 0x3FC ) ) ;
2016-12-03 16:58:24 +00:00
}
2017-01-30 17:36:11 +00:00
void T_PUSH ( ARM * cpu )
2016-12-03 14:15:34 +00:00
{
int nregs = 0 ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 14:15:34 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
nregs + + ;
}
if ( cpu - > CurInstr & ( 1 < < 8 ) )
nregs + + ;
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ 13 ] ;
2016-12-03 14:15:34 +00:00
base - = ( nregs < < 2 ) ;
2024-06-06 22:58:43 +00:00
u32 wbbase = base ;
2016-12-03 14:15:34 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
2024-07-12 00:06:56 +00:00
if ( ! ( first ? cpu - > DataWrite32 ( base , cpu - > R [ i ] )
: cpu - > DataWrite32S ( base , cpu - > R [ i ] ) ) )
2024-06-06 22:58:43 +00:00
{
goto dataabort ;
}
2018-12-09 00:17:05 +00:00
first = false ;
2016-12-03 14:15:34 +00:00
base + = 4 ;
}
}
if ( cpu - > CurInstr & ( 1 < < 8 ) )
{
2024-06-06 22:58:43 +00:00
if ( ! ( first ? cpu - > DataWrite32 ( base , cpu - > R [ 14 ] )
: cpu - > DataWrite32S ( base , cpu - > R [ 14 ] ) ) )
{
goto dataabort ;
}
2016-12-03 14:15:34 +00:00
}
2018-12-04 16:54:10 +00:00
2024-06-06 22:58:43 +00:00
cpu - > R [ 13 ] = wbbase ;
dataabort :
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CD ( ) ;
2016-12-03 14:15:34 +00:00
}
2024-07-12 00:06:56 +00:00
void T_POP ( ARM * cpu )
2016-12-03 14:15:34 +00:00
{
2024-06-17 22:07:53 +00:00
u32 base = cpu - > R [ 13 ] ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 14:15:34 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
2024-06-06 23:05:28 +00:00
if ( ! ( first ? cpu - > DataRead32 ( base , & cpu - > R [ i ] )
: cpu - > DataRead32S ( base , & cpu - > R [ i ] ) ) )
{
goto dataabort ;
}
2018-12-09 00:17:05 +00:00
first = false ;
2016-12-03 14:15:34 +00:00
base + = 4 ;
}
}
if ( cpu - > CurInstr & ( 1 < < 8 ) )
{
2018-12-04 16:54:10 +00:00
u32 pc ;
2024-06-06 23:05:28 +00:00
if ( ! ( first ? cpu - > DataRead32 ( base , & pc )
: cpu - > DataRead32S ( base , & pc ) ) )
{
goto dataabort ;
}
2024-08-04 18:45:28 +00:00
if ( cpu - > Num = = 1 | | ( ( ( ARMv5 * ) cpu ) - > CP15Control & ( 1 < < 15 ) ) ) pc | = 0x1 ;
2016-12-03 14:15:34 +00:00
cpu - > JumpTo ( pc ) ;
base + = 4 ;
}
cpu - > R [ 13 ] = base ;
2024-06-17 00:44:55 +00:00
2024-06-06 23:05:28 +00:00
dataabort :
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ;
2016-12-03 14:15:34 +00:00
}
2017-01-30 17:36:11 +00:00
void T_STMIA ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ ( cpu - > CurInstr > > 8 ) & 0x7 ] ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 17:29:19 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
2024-07-12 00:06:56 +00:00
if ( ! ( first ? cpu - > DataWrite32 ( base , cpu - > R [ i ] )
: cpu - > DataWrite32S ( base , cpu - > R [ i ] ) ) )
2024-06-06 22:58:43 +00:00
{
goto dataabort ;
}
2018-12-09 00:17:05 +00:00
first = false ;
2016-12-03 17:29:19 +00:00
base + = 4 ;
}
}
2017-01-23 01:26:05 +00:00
// TODO: check "Rb included in Rlist" case
2016-12-03 17:29:19 +00:00
cpu - > R [ ( cpu - > CurInstr > > 8 ) & 0x7 ] = base ;
2024-06-06 22:58:43 +00:00
dataabort :
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CD ( ) ;
2016-12-03 17:29:19 +00:00
}
2017-01-30 17:36:11 +00:00
void T_LDMIA ( ARM * cpu )
2016-12-03 17:29:19 +00:00
{
2024-07-12 00:06:56 +00:00
u32 base = cpu - > R [ ( cpu - > CurInstr > > 8 ) & 0x7 ] ;
2018-12-09 00:17:05 +00:00
bool first = true ;
2016-12-03 17:29:19 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
if ( cpu - > CurInstr & ( 1 < < i ) )
{
2024-06-06 23:05:28 +00:00
if ( ! ( first ? cpu - > DataRead32 ( base , & cpu - > R [ i ] )
: cpu - > DataRead32S ( base , & cpu - > R [ i ] ) ) )
{
goto dataabort ;
}
2018-12-09 00:17:05 +00:00
first = false ;
2016-12-03 17:29:19 +00:00
base + = 4 ;
}
}
2017-01-23 01:26:05 +00:00
if ( ! ( cpu - > CurInstr & ( 1 < < ( ( cpu - > CurInstr > > 8 ) & 0x7 ) ) ) )
cpu - > R [ ( cpu - > CurInstr > > 8 ) & 0x7 ] = base ;
2018-12-04 16:54:10 +00:00
2024-06-06 23:05:28 +00:00
dataabort :
2024-08-04 18:45:28 +00:00
cpu - > AddCycles_CDI ( ) ;
2016-12-03 17:29:19 +00:00
}
2016-12-03 14:15:34 +00:00
2016-12-03 00:31:33 +00:00
}