2024-08-14 16:02:39 +08:00
using System ;
2024-08-15 13:19:43 +08:00
using System.Collections.Generic ;
2024-08-14 16:02:39 +08:00
using System.Numerics ;
using System.Runtime.CompilerServices ;
using System.Runtime.InteropServices ;
using static Iris . CPU . CPU_Core ;
namespace Iris.CPU
{
internal sealed class ARM_Interpreter
{
private readonly CPU_Core _cpu ;
private readonly InstructionLUTEntry < UInt32 > [ ] _instructionLUT = new InstructionLUTEntry < UInt32 > [ 1 < < 12 ] ;
internal ARM_Interpreter ( CPU_Core cpu )
{
_cpu = cpu ;
unsafe
{
InstructionListEntry < UInt32 > [ ] InstructionList =
2024-08-15 13:19:43 +08:00
{
2024-08-14 16:02:39 +08:00
// ADC
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x02a0 _0000 , & ADC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00a0 _0000 , & ADC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00a0 _0080 , & ADC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00a0 _0010 , & ADC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// ADD
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0280 _0000 , & ADD , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0080 _0000 , & ADD , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0080 _0080 , & ADD , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0080 _0010 , & ADD , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// AND
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0200 _0000 , & AND , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0000 _0000 , & AND , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0000 _0080 , & AND , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0000 _0010 , & AND , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// B
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0f00 _0000 , 0x0a00 _0000 , & B , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// BL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0f00 _0000 , 0x0b00 _0000 , & BL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// BIC
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x03c0 _0000 , & BIC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x01c0 _0000 , & BIC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x01c0 _0080 , & BIC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x01c0 _0010 , & BIC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// BX
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fff _fff0 , 0x012f _ff10 , & BX , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// CMN
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0370 _0000 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _0000 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _0080 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _0010 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0370 _f000 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _f000 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _f080 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0170 _f010 , & CMN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// CMP
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0350 _0000 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _0000 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _0080 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _0010 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0350 _f000 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _f000 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _f080 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0150 _f010 , & CMP , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// EOR
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0220 _0000 , & EOR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0020 _0000 , & EOR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0020 _0080 , & EOR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0020 _0010 , & EOR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// LDM
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e50 _0000 , 0x0810 _0000 , & LDM1 , new List < Model > ( ) { Model . ARM7TDMI } ) ,
new InstructionListEntry < uint > ( 0x0e50 _8000 , 0x0850 _0000 , & LDM2 , new List < Model > ( ) { Model . ARM7TDMI } ) ,
//new InstructionListEntry<uint>(0x0e50_8000, 0x0850_8000, &LDM3, new List<Model>{ Model.ARM7TDMI }),
2024-08-14 16:02:39 +08:00
// LDR
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0c50 _0000 , 0x0410 _0000 , & LDR , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// LDRB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0c50 _0000 , 0x0450 _0000 , & LDRB , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// LDRH
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e10 _00f0 , 0x0010 _00b0 , & LDRH , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// LDRSB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e10 _00f0 , 0x0010 _00d0 , & LDRSB , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// LDRSH
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e10 _00f0 , 0x0010 _00f0 , & LDRSH , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// MLA
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _00f0 , 0x0020 _0090 , & MLA , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// MOV
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fef _0000 , 0x03a0 _0000 , & MOV , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01a0 _0000 , & MOV , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01a0 _0080 , & MOV , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01a0 _0010 , & MOV , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// MRS
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fbf _0fff , 0x010f _0000 , & MRS , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// MSR
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fb0 _f000 , 0x0320 _f000 , & MSR , new List < Model > ( ) { Model . ARM7TDMI } ) , // Immediate operand
new InstructionListEntry < uint > ( 0x0fb0 _fff0 , 0x0120 _f000 , & MSR , new List < Model > ( ) { Model . ARM7TDMI } ) , // Register operand
2024-08-14 16:02:39 +08:00
// MUL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _f0f0 , 0x0000 _0090 , & MUL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// MVN
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fef _0000 , 0x03e0 _0000 , & MVN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01e0 _0000 , & MVN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01e0 _0080 , & MVN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fef _0090 , 0x01e0 _0010 , & MVN , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// ORR
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0380 _0000 , & ORR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0180 _0000 , & ORR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0180 _0080 , & ORR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0180 _0010 , & ORR , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// RSB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0260 _0000 , & RSB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0060 _0000 , & RSB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0060 _0080 , & RSB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0060 _0010 , & RSB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// RSC
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x02e0 _0000 , & RSC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00e0 _0000 , & RSC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00e0 _0080 , & RSC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00e0 _0010 , & RSC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// SBC
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x02c0 _0000 , & SBC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00c0 _0000 , & SBC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00c0 _0080 , & SBC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x00c0 _0010 , & SBC , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// SMLAL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _00f0 , 0x00e0 _0090 , & SMLAL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// SMULL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _00f0 , 0x00c0 _0090 , & SMULL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// STM
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e50 _0000 , 0x0800 _0000 , & STM1 , new List < Model > ( ) { Model . ARM7TDMI } ) ,
new InstructionListEntry < uint > ( 0x0e70 _0000 , 0x0840 _0000 , & STM2 , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// STR
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0c50 _0000 , 0x0400 _0000 , & STR , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// STRB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0c50 _0000 , 0x0440 _0000 , & STRB , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// STRH
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0e10 _00f0 , 0x0000 _00b0 , & STRH , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// SUB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _0000 , 0x0240 _0000 , & SUB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0040 _0000 , & SUB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0040 _0080 , & SUB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0fe0 _0090 , 0x0040 _0010 , & SUB , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// SWI
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0f00 _0000 , 0x0f00 _0000 , & SWI , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// SWP
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _0ff0 , 0x0100 _0090 , & SWP , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// SWPB
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _0ff0 , 0x0140 _0090 , & SWPB , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// TEQ
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0330 _0000 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _0000 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _0080 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _0010 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0330 _f000 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _f000 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _f080 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0130 _f010 , & TEQ , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// TST
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0310 _0000 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _0000 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _0080 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _0010 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
new InstructionListEntry < uint > ( 0x0ff0 _f000 , 0x0310 _f000 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 1
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _f000 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _f080 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 1 and bit[4] is 0
new InstructionListEntry < uint > ( 0x0ff0 _f090 , 0x0110 _f010 , & TST , new List < Model > ( ) { Model . ARM7TDMI } ) , // I bit is 0, bit[7] is 0 and bit[4] is 1
2024-08-14 16:02:39 +08:00
// UMLAL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _00f0 , 0x00a0 _0090 , & UMLAL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
2024-08-14 16:02:39 +08:00
// UMULL
2024-08-15 13:19:43 +08:00
new InstructionListEntry < uint > ( 0x0fe0 _00f0 , 0x0080 _0090 , & UMULL , new List < Model > ( ) { Model . ARM7TDMI } ) ,
} ;
2024-08-14 16:02:39 +08:00
for ( UInt32 instruction = 0 ; instruction < _instructionLUT . Length ; + + instruction )
{
bool unknownInstruction = true ;
foreach ( InstructionListEntry < UInt32 > entry in InstructionList )
{
if ( ( ( instruction & InstructionLUTHash ( entry . _mask ) ) = = InstructionLUTHash ( entry . _expected ) ) & & ( entry . _modelList . Contains ( _cpu . _model ) ) )
{
_instructionLUT [ instruction ] = new ( entry . _handler ) ;
unknownInstruction = false ;
break ;
}
}
if ( unknownInstruction )
_instructionLUT [ instruction ] = new ( & UNKNOWN ) ;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static UInt32 InstructionLUTHash ( UInt32 value )
{
return ( ( value > > 16 ) & 0xff0 ) | ( ( value > > 4 ) & 0x00f ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal UInt64 Step ( )
{
UInt32 instruction = _cpu . _callbackInterface . _read32 ( _cpu . NextInstructionAddress ) ;
_cpu . NextInstructionAddress + = 4 ;
UInt32 cond = ( instruction > > 28 ) & 0 b1111 ;
if ( _cpu . ConditionPassed ( cond ) )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( _cpu . Reg ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
regPC = _cpu . NextInstructionAddress + 4 ;
2024-08-15 13:19:43 +08:00
ref InstructionLUTEntry < UInt32 > instructionLUTDataRef = ref MyUnSafeCommon . GetArrayDataReference ( _instructionLUT ) ;
ref InstructionLUTEntry < UInt32 > instructionLUTEntry = ref Unsafe . Add ( ref instructionLUTDataRef , ( int ) InstructionLUTHash ( instruction ) ) ;
2024-08-14 16:02:39 +08:00
unsafe
{
return instructionLUTEntry . _handler ( _cpu , instruction ) ;
}
}
else
{
return 1 ;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void SetPC ( CPU_Core cpu , UInt32 value )
{
cpu . NextInstructionAddress = value ;
}
private static void SetReg ( CPU_Core cpu , UInt32 i , UInt32 value )
{
if ( i = = PC )
{
SetPC ( cpu , value ) ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRi = ref Unsafe . Add ( ref regDataRef , ( int ) i ) ;
2024-08-14 16:02:39 +08:00
regRi = value ;
}
}
// Addressing mode 1
private static ( UInt32 shifterOperand , UInt32 shifterCarryOut ) GetShifterOperand ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 shifterOperand = 0 ;
UInt32 shifterCarryOut = 0 ;
if ( i = = 1 ) // 32-bit immediate
{
UInt32 rotateImm = ( instruction > > 8 ) & 0 b1111 ;
UInt32 imm = instruction & 0xff ;
2024-08-15 13:19:43 +08:00
shifterOperand = MyBitOperations . RotateRight ( imm , ( int ) ( rotateImm * 2 ) ) ;
2024-08-14 16:02:39 +08:00
shifterCarryOut = ( rotateImm = = 0 ) ? cpu . GetFlag ( Flag . C ) : ( shifterOperand > > 31 ) ;
}
else
{
UInt32 shift = ( instruction > > 5 ) & 0 b11 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
if ( r = = 0 ) // Immediate shifts
{
UInt32 shiftImm = ( instruction > > 7 ) & 0 b1_1111 ;
UInt32 value = regRm ;
int shiftAmount = ( int ) shiftImm ;
switch ( shift )
{
case 0 b00 : // Logical shift left
if ( shiftAmount = = 0 )
{
shifterOperand = value ;
shifterCarryOut = cpu . GetFlag ( Flag . C ) ;
}
else
{
shifterOperand = value < < shiftAmount ;
shifterCarryOut = ( value > > ( 32 - shiftAmount ) ) & 1 ;
}
break ;
case 0 b01 : // Logical shift right
if ( shiftAmount = = 0 )
{
shifterOperand = 0 ;
shifterCarryOut = value > > 31 ;
}
else
{
shifterOperand = value > > shiftAmount ;
shifterCarryOut = ( value > > ( shiftAmount - 1 ) ) & 1 ;
}
break ;
case 0 b10 : // Arithmetic shift right
if ( shiftAmount = = 0 )
{
shifterOperand = ( ( value > > 31 ) = = 0 ) ? 0 : 0xffff _ffff ;
shifterCarryOut = value > > 31 ;
}
else
{
shifterOperand = ArithmeticShiftRight ( value , shiftAmount ) ;
shifterCarryOut = ( value > > ( shiftAmount - 1 ) ) & 1 ;
}
break ;
case 0 b11 : // Rotate right
if ( shiftAmount = = 0 )
{
shifterOperand = ( cpu . GetFlag ( Flag . C ) < < 31 ) | ( value > > 1 ) ;
shifterCarryOut = value & 1 ;
}
else
{
2024-08-15 13:19:43 +08:00
shifterOperand = MyBitOperations . RotateRight ( value , shiftAmount ) ;
2024-08-14 16:02:39 +08:00
shifterCarryOut = ( value > > ( shiftAmount - 1 ) ) & 1 ;
}
break ;
}
}
else // Register shifts
{
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
UInt32 value = ( rm = = PC ) ? ( regPC + 4 ) : regRm ;
int shiftAmount = ( int ) ( regRs & 0xff ) ;
switch ( shift )
{
case 0 b00 : // Logical shift left
if ( shiftAmount = = 0 )
{
shifterOperand = value ;
shifterCarryOut = cpu . GetFlag ( Flag . C ) ;
}
else if ( shiftAmount < 32 )
{
shifterOperand = value < < shiftAmount ;
shifterCarryOut = ( value > > ( 32 - shiftAmount ) ) & 1 ;
}
else if ( shiftAmount = = 32 )
{
shifterOperand = 0 ;
shifterCarryOut = value & 1 ;
}
else
{
shifterOperand = 0 ;
shifterCarryOut = 0 ;
}
break ;
case 0 b01 : // Logical shift right
if ( shiftAmount = = 0 )
{
shifterOperand = value ;
shifterCarryOut = cpu . GetFlag ( Flag . C ) ;
}
else if ( shiftAmount < 32 )
{
shifterOperand = value > > shiftAmount ;
shifterCarryOut = ( value > > ( shiftAmount - 1 ) ) & 1 ;
}
else if ( shiftAmount = = 32 )
{
shifterOperand = 0 ;
shifterCarryOut = value > > 31 ;
}
else
{
shifterOperand = 0 ;
shifterCarryOut = 0 ;
}
break ;
case 0 b10 : // Arithmetic shift right
if ( shiftAmount = = 0 )
{
shifterOperand = value ;
shifterCarryOut = cpu . GetFlag ( Flag . C ) ;
}
else if ( shiftAmount < 32 )
{
shifterOperand = ArithmeticShiftRight ( value , shiftAmount ) ;
shifterCarryOut = ( value > > ( shiftAmount - 1 ) ) & 1 ;
}
else
{
shifterOperand = ( ( value > > 31 ) = = 0 ) ? 0 : 0xffff _ffff ;
shifterCarryOut = value > > 31 ;
}
break ;
case 0 b11 : // Rotate right
if ( shiftAmount = = 0 )
{
shifterOperand = value ;
shifterCarryOut = cpu . GetFlag ( Flag . C ) ;
}
else if ( ( shiftAmount & 0 b1_1111 ) = = 0 )
{
shifterOperand = value ;
shifterCarryOut = value > > 31 ;
}
else
{
2024-08-15 13:19:43 +08:00
shifterOperand = MyBitOperations . RotateRight ( value , shiftAmount & 0 b1_1111 ) ;
2024-08-14 16:02:39 +08:00
shifterCarryOut = ( value > > ( ( shiftAmount & 0 b1_1111 ) - 1 ) ) & 1 ;
}
break ;
}
}
}
return ( shifterOperand , shifterCarryOut ) ;
}
// Addressing mode 2
private static UInt32 GetAddress ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 p = ( instruction > > 24 ) & 1 ;
UInt32 u = ( instruction > > 23 ) & 1 ;
UInt32 w = ( instruction > > 21 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
2024-08-14 16:02:39 +08:00
UInt32 index = 0 ;
if ( i = = 0 ) // Immediate
{
UInt32 offset = instruction & 0xfff ;
index = offset ;
}
else
{
UInt32 shiftImm = ( instruction > > 7 ) & 0 b1_1111 ;
UInt32 shift = ( instruction > > 5 ) & 0 b11 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
if ( ( shiftImm = = 0 ) & & ( shift = = 0 ) ) // Register
{
index = regRm ;
}
else // Scaled register
{
switch ( shift )
{
case 0 b00 : // LSL
index = regRm < < ( int ) shiftImm ;
break ;
case 0 b01 : // LSR
if ( shiftImm = = 0 )
index = 0 ;
else
index = regRm > > ( int ) shiftImm ;
break ;
case 0 b10 : // ASR
if ( shiftImm = = 0 )
index = ( ( regRm > > 31 ) = = 1 ) ? 0xffff _ffff : 0 ;
else
index = ArithmeticShiftRight ( regRm , ( int ) shiftImm ) ;
break ;
case 0 b11 :
if ( shiftImm = = 0 ) // RRX
index = ( cpu . GetFlag ( Flag . C ) < < 31 ) | ( regRm > > 1 ) ;
else // ROR
2024-08-15 13:19:43 +08:00
index = MyBitOperations . RotateRight ( regRm , ( int ) shiftImm ) ;
2024-08-14 16:02:39 +08:00
break ;
}
}
}
UInt32 regRnIndexed = ( u = = 1 ) ? ( regRn + index ) : ( regRn - index ) ;
UInt32 address ;
if ( p = = 0 ) // Post-indexed
{
address = regRn ;
SetReg ( cpu , rn , regRnIndexed ) ;
}
else if ( w = = 0 ) // Offset
{
address = regRnIndexed ;
}
else // Pre-indexed
{
address = regRnIndexed ;
SetReg ( cpu , rn , regRnIndexed ) ;
}
return address ;
}
// Addressing mode 3
private static UInt32 GetAddress_Misc ( CPU_Core cpu , UInt32 instruction )
{
UInt32 p = ( instruction > > 24 ) & 1 ;
UInt32 u = ( instruction > > 23 ) & 1 ;
UInt32 i = ( instruction > > 22 ) & 1 ;
UInt32 w = ( instruction > > 21 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
2024-08-14 16:02:39 +08:00
UInt32 index ;
if ( i = = 1 ) // Immediate
{
UInt32 immH = ( instruction > > 8 ) & 0 b1111 ;
UInt32 immL = instruction & 0 b1111 ;
UInt32 offset = ( immH < < 4 ) | immL ;
index = offset ;
}
else // Register
{
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
index = regRm ;
}
UInt32 regRnIndexed = ( u = = 1 ) ? ( regRn + index ) : ( regRn - index ) ;
UInt32 address ;
if ( p = = 0 ) // Post-indexed
{
address = regRn ;
SetReg ( cpu , rn , regRnIndexed ) ;
}
else if ( w = = 0 ) // Offset
{
address = regRnIndexed ;
}
else // Pre-indexed
{
address = regRnIndexed ;
SetReg ( cpu , rn , regRnIndexed ) ;
}
return address ;
}
// Addressing mode 4
private static ( UInt32 startAddress , UInt32 endAddress ) GetAddress_Multiple ( CPU_Core cpu , UInt32 instruction )
{
UInt32 p = ( instruction > > 24 ) & 1 ;
UInt32 u = ( instruction > > 23 ) & 1 ;
UInt32 w = ( instruction > > 21 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 registerList = instruction & 0xffff ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
2024-08-14 16:02:39 +08:00
2024-08-15 13:19:43 +08:00
UInt32 increment = ( registerList = = 0 ) ? 0x40 : ( ( UInt32 ) MyBitOperations . PopCount ( registerList ) * 4 ) ;
2024-08-14 16:02:39 +08:00
UInt32 startAddress , endAddress ;
UInt32 value ;
if ( u = = 1 ) // increment
{
value = regRn + increment ;
if ( p = = 0 ) // after
{
startAddress = regRn ;
endAddress = value - 4 ;
}
else // before
{
startAddress = regRn + 4 ;
endAddress = value ;
}
}
else // decrement
{
value = regRn - increment ;
if ( p = = 0 ) // after
{
startAddress = value + 4 ;
endAddress = regRn ;
}
else // before
{
startAddress = value ;
endAddress = regRn - 4 ;
}
}
if ( w = = 1 )
SetReg ( cpu , rn , value ) ;
return ( startAddress , endAddress ) ;
}
private static UInt64 UNKNOWN ( CPU_Core cpu , UInt32 instruction )
{
throw new Exception ( string . Format ( "Iris.CPU.ARM_Interpreter: Unknown ARM instruction 0x{0:x8} at address 0x{1:x8}" , instruction , cpu . NextInstructionAddress - 4 ) ) ;
}
private static UInt64 ADC ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand + ( UInt64 ) rightOperand + ( UInt64 ) cpu . GetFlag ( Flag . C ) ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , CarryFrom ( result ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Addition ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 ADD ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand + ( UInt64 ) rightOperand ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , CarryFrom ( result ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Addition ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 AND ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
SetReg ( cpu , rd , leftOperand & rightOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 B ( CPU_Core cpu , UInt32 instruction )
{
UInt32 imm = instruction & 0xff _ffff ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
SetPC ( cpu , regPC + ( SignExtend ( imm , 24 ) < < 2 ) ) ;
return 3 ;
}
private static UInt64 BL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 imm = instruction & 0xff _ffff ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regLR = ref Unsafe . Add ( ref regDataRef , ( int ) LR ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
regLR = cpu . NextInstructionAddress ;
SetPC ( cpu , regPC + ( SignExtend ( imm , 24 ) < < 2 ) ) ;
return 3 ;
}
private static UInt64 BIC ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
SetReg ( cpu , rd , leftOperand & ~ rightOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 BX ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
cpu . CPSR = ( cpu . CPSR & ~ ( 1 u < < 5 ) ) | ( ( regRm & 1 ) < < 5 ) ;
SetPC ( cpu , regRm & 0xffff _fffe ) ;
return 3 ;
}
private static UInt64 CMN ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand + ( UInt64 ) rightOperand ;
UInt32 aluOut = ( UInt32 ) result ;
if ( rd = = PC )
{
if ( ( cpu . CPSR & ModeMask ) = = UserMode )
cpu . CPSR = ( cpu . CPSR & ~ 0xf000 _0000 ) | ( aluOut & 0xf000 _0000 ) ;
else
cpu . SetCPSR ( ( cpu . CPSR & ~ 0xf000 _00c3 ) | ( aluOut & 0xf000 _0003 ) | ( ( ( aluOut > > 26 ) & 0 b11 ) < < 6 ) ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
cpu . SetFlag ( Flag . N , aluOut > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( aluOut = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , CarryFrom ( result ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Addition ( leftOperand , rightOperand , aluOut ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
private static UInt64 CMP ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand - ( UInt64 ) rightOperand ;
UInt32 aluOut = ( UInt32 ) result ;
if ( rd = = PC )
{
if ( ( cpu . CPSR & ModeMask ) = = UserMode )
cpu . CPSR = ( cpu . CPSR & ~ 0xf000 _0000 ) | ( aluOut & 0xf000 _0000 ) ;
else
cpu . SetCPSR ( ( cpu . CPSR & ~ 0xf000 _00c3 ) | ( aluOut & 0xf000 _0003 ) | ( ( ( aluOut > > 26 ) & 0 b11 ) < < 6 ) ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
cpu . SetFlag ( Flag . N , aluOut > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( aluOut = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , Not ( BorrowFrom ( result ) ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Subtraction ( leftOperand , rightOperand , aluOut ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
private static UInt64 EOR ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
SetReg ( cpu , rd , leftOperand ^ rightOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 LDM1 ( CPU_Core cpu , UInt32 instruction )
{
UInt32 registerList = instruction & 0xffff ;
( UInt32 startAddress , _ ) = GetAddress_Multiple ( cpu , instruction ) ;
UInt32 address = startAddress ;
if ( registerList = = 0 )
{
SetPC ( cpu , cpu . _callbackInterface . _read32 ( address ) ) ;
return 5 ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
2024-08-14 16:02:39 +08:00
for ( int i = 0 ; i < = 14 ; + + i )
{
if ( ( ( registerList > > i ) & 1 ) = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRi = ref Unsafe . Add ( ref regDataRef , ( int ) i ) ;
2024-08-14 16:02:39 +08:00
regRi = cpu . _callbackInterface . _read32 ( address ) ;
address + = 4 ;
}
}
2024-08-15 13:19:43 +08:00
UInt32 n = ( UInt32 ) MyBitOperations . PopCount ( registerList ) ;
2024-08-14 16:02:39 +08:00
if ( ( ( registerList > > 15 ) & 1 ) = = 1 )
{
SetPC ( cpu , cpu . _callbackInterface . _read32 ( address ) & 0xffff _fffc ) ;
return n + 4 ;
}
else
{
return n + 2 ;
}
}
}
private static UInt64 LDM2 ( CPU_Core cpu , UInt32 instruction )
{
UInt32 registerList = instruction & 0x7fff ;
( UInt32 startAddress , _ ) = GetAddress_Multiple ( cpu , instruction ) ;
UInt32 address = startAddress ;
if ( registerList = = 0 )
{
SetPC ( cpu , cpu . _callbackInterface . _read32 ( address ) ) ;
return 5 ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
2024-08-14 16:02:39 +08:00
for ( int i = 0 ; i < = 14 ; + + i )
{
if ( ( ( registerList > > i ) & 1 ) = = 1 )
{
UInt32 value = cpu . _callbackInterface . _read32 ( address ) ;
switch ( i )
{
case 8 :
cpu . Reg8_usr = value ;
break ;
case 9 :
cpu . Reg9_usr = value ;
break ;
case 10 :
cpu . Reg10_usr = value ;
break ;
case 11 :
cpu . Reg11_usr = value ;
break ;
case 12 :
cpu . Reg12_usr = value ;
break ;
case 13 :
cpu . Reg13_usr = value ;
break ;
case 14 :
cpu . Reg14_usr = value ;
break ;
default :
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRi = ref Unsafe . Add ( ref regDataRef , ( int ) i ) ;
2024-08-14 16:02:39 +08:00
regRi = value ;
break ;
}
}
address + = 4 ;
}
}
2024-08-15 13:19:43 +08:00
UInt32 n = ( UInt32 ) MyBitOperations . PopCount ( registerList ) ;
2024-08-14 16:02:39 +08:00
return n + 2 ;
}
}
private static UInt64 LDR ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 address = GetAddress ( cpu , instruction ) ;
2024-08-15 13:19:43 +08:00
UInt32 data = MyBitOperations . RotateRight ( cpu . _callbackInterface . _read32 ( address ) , ( int ) ( 8 * ( address & 0 b11 ) ) ) ;
2024-08-14 16:02:39 +08:00
if ( rd = = PC )
{
SetPC ( cpu , data & 0xffff _fffc ) ;
return 5 ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
regRd = data ;
return 3 ;
}
}
private static UInt64 LDRB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 address = GetAddress ( cpu , instruction ) ;
Byte data = cpu . _callbackInterface . _read8 ( address ) ;
SetReg ( cpu , rd , data ) ;
return ( rd = = PC ) ? 5 u : 3 u ;
}
private static UInt64 LDRH ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 address = GetAddress_Misc ( cpu , instruction ) ;
2024-08-15 13:19:43 +08:00
UInt32 data = MyBitOperations . RotateRight ( cpu . _callbackInterface . _read16 ( address ) , ( int ) ( 8 * ( address & 1 ) ) ) ;
2024-08-14 16:02:39 +08:00
SetReg ( cpu , rd , data ) ;
return ( rd = = PC ) ? 5 u : 3 u ;
}
private static UInt64 LDRSB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 address = GetAddress_Misc ( cpu , instruction ) ;
Byte data = cpu . _callbackInterface . _read8 ( address ) ;
SetReg ( cpu , rd , SignExtend ( data , 8 ) ) ;
return ( rd = = PC ) ? 5 u : 3 u ;
}
private static UInt64 LDRSH ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 address = GetAddress_Misc ( cpu , instruction ) ;
if ( ( address & 1 ) = = 1 )
{
Byte data = cpu . _callbackInterface . _read8 ( address ) ;
SetReg ( cpu , rd , SignExtend ( data , 8 ) ) ;
}
else
{
UInt16 data = cpu . _callbackInterface . _read16 ( address ) ;
SetReg ( cpu , rd , SignExtend ( data , 16 ) ) ;
}
return ( rd = = PC ) ? 5 u : 3 u ;
}
private static UInt64 MLA ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rd = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rn = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
SetReg ( cpu , rd , ( regRm * regRs ) + regRn ) ;
if ( s = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
}
return m + 2 ;
}
private static UInt64 MOV ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
SetReg ( cpu , rd , shifterOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 MRS ( CPU_Core cpu , UInt32 instruction )
{
UInt32 r = ( instruction > > 22 ) & 1 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
SetReg ( cpu , rd , ( r = = 1 ) ? cpu . SPSR : cpu . CPSR ) ;
return 1 ;
}
private static UInt64 MSR ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 r = ( instruction > > 22 ) & 1 ;
UInt32 fieldMask = ( instruction > > 16 ) & 0 b1111 ;
UInt32 operand ;
if ( i = = 1 )
{
UInt32 rotateImm = ( instruction > > 8 ) & 0 b1111 ;
UInt32 imm = instruction & 0xff ;
2024-08-15 13:19:43 +08:00
operand = MyBitOperations . RotateRight ( imm , ( int ) ( 2 * rotateImm ) ) ;
2024-08-14 16:02:39 +08:00
}
else
{
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
operand = regRm ;
}
UInt32 mask = ( UInt32 ) ( ( ( ( fieldMask > > 0 ) & 1 ) = = 1 ) ? 0x0000 _00ff : 0 )
| ( UInt32 ) ( ( ( ( fieldMask > > 1 ) & 1 ) = = 1 ) ? 0x0000 _ff00 : 0 )
| ( UInt32 ) ( ( ( ( fieldMask > > 2 ) & 1 ) = = 1 ) ? 0x00ff _0000 : 0 )
| ( UInt32 ) ( ( ( ( fieldMask > > 3 ) & 1 ) = = 1 ) ? 0xff00 _0000 : 0 ) ;
if ( r = = 0 )
{
if ( ( cpu . CPSR & ModeMask ) = = UserMode )
{
mask & = 0xff00 _0000 ;
cpu . CPSR = ( cpu . CPSR & ~ mask ) | ( operand & mask ) ;
}
else
{
cpu . SetCPSR ( ( cpu . CPSR & ~ mask ) | ( operand & mask ) ) ;
}
}
else
{
cpu . SPSR = ( cpu . SPSR & ~ mask ) | ( operand & mask ) ;
}
return 1 ;
}
private static UInt64 MUL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rd = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
SetReg ( cpu , rd , regRm * regRs ) ;
if ( s = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
}
return m + 1 ;
}
private static UInt64 MVN ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
SetReg ( cpu , rd , ~ shifterOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 ORR ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
SetReg ( cpu , rd , leftOperand | rightOperand ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 RSB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = shifterOperand ;
UInt32 rightOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt64 result = ( UInt64 ) leftOperand - ( UInt64 ) rightOperand ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , Not ( BorrowFrom ( result ) ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Subtraction ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 RSC ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = shifterOperand ;
UInt32 rightOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt64 result = ( UInt64 ) leftOperand - ( UInt64 ) rightOperand - ( UInt64 ) Not ( cpu . GetFlag ( Flag . C ) ) ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , Not ( BorrowFrom ( result ) ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Subtraction ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 SBC ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand - ( UInt64 ) rightOperand - ( UInt64 ) Not ( cpu . GetFlag ( Flag . C ) ) ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , Not ( BorrowFrom ( result ) ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Subtraction ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 SMLAL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rdHi = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rdLo = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRdHi = ref Unsafe . Add ( ref regDataRef , ( int ) rdHi ) ;
ref UInt32 regRdLo = ref Unsafe . Add ( ref regDataRef , ( int ) rdLo ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
Int64 result = ( Int64 ) ( Int32 ) regRm * ( Int64 ) ( Int32 ) regRs ;
UInt64 resultLo = ( UInt64 ) ( UInt32 ) result + ( UInt64 ) regRdLo ;
UInt32 resultHi = ( UInt32 ) ( result > > 32 ) + regRdHi + CarryFrom ( resultLo ) ;
SetReg ( cpu , rdLo , ( UInt32 ) resultLo ) ;
SetReg ( cpu , rdHi , resultHi ) ;
if ( s = = 1 )
{
cpu . SetFlag ( Flag . N , regRdHi > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( ( regRdHi = = 0 ) & & ( regRdLo = = 0 ) ) ? 1 u : 0 u ) ;
}
return m + 3 ;
}
private static UInt64 SMULL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rdHi = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rdLo = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
Int64 result = ( Int64 ) ( Int32 ) regRm * ( Int64 ) ( Int32 ) regRs ;
SetReg ( cpu , rdLo , ( UInt32 ) result ) ;
SetReg ( cpu , rdHi , ( UInt32 ) ( result > > 32 ) ) ;
if ( s = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRdHi = ref Unsafe . Add ( ref regDataRef , ( int ) rdHi ) ;
ref UInt32 regRdLo = ref Unsafe . Add ( ref regDataRef , ( int ) rdLo ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRdHi > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( ( regRdHi = = 0 ) & & ( regRdLo = = 0 ) ) ? 1 u : 0 u ) ;
}
return m + 2 ;
}
private static UInt64 STM1 ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 registerList = instruction & 0xffff ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
2024-08-14 16:02:39 +08:00
UInt32 oldRegRn = regRn ;
( UInt32 startAddress , _ ) = GetAddress_Multiple ( cpu , instruction ) ;
UInt32 address = startAddress ;
if ( registerList = = 0 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( address , regPC + 4 ) ;
return 2 ;
}
else
{
for ( int i = 0 ; i < = 14 ; + + i )
{
if ( ( ( registerList > > i ) & 1 ) = = 1 )
{
if ( ( i = = rn ) & & ( ( registerList & ~ ( 0xffff < < i ) ) = = 0 ) )
{
cpu . _callbackInterface . _write32 ( address , oldRegRn ) ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRi = ref Unsafe . Add ( ref regDataRef , ( int ) i ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( address , regRi ) ;
}
address + = 4 ;
}
}
if ( ( ( registerList > > 15 ) & 1 ) = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( address , regPC + 4 ) ;
}
2024-08-15 13:19:43 +08:00
UInt32 n = ( UInt32 ) MyBitOperations . PopCount ( registerList ) ;
2024-08-14 16:02:39 +08:00
return n + 1 ;
}
}
private static UInt64 STM2 ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 registerList = instruction & 0xffff ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
2024-08-14 16:02:39 +08:00
UInt32 oldRegRn = rn switch
{
8 = > cpu . Reg8_usr ,
9 = > cpu . Reg9_usr ,
10 = > cpu . Reg10_usr ,
11 = > cpu . Reg11_usr ,
12 = > cpu . Reg12_usr ,
13 = > cpu . Reg13_usr ,
14 = > cpu . Reg14_usr ,
2024-08-15 13:19:43 +08:00
_ = > Unsafe . Add ( ref regDataRef , ( int ) rn ) ,
2024-08-14 16:02:39 +08:00
} ;
( UInt32 startAddress , _ ) = GetAddress_Multiple ( cpu , instruction ) ;
UInt32 address = startAddress ;
if ( registerList = = 0 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( address , regPC + 4 ) ;
return 2 ;
}
else
{
for ( int i = 0 ; i < = 14 ; + + i )
{
if ( ( ( registerList > > i ) & 1 ) = = 1 )
{
if ( ( i = = rn ) & & ( ( registerList & ~ ( 0xffff < < i ) ) = = 0 ) )
{
cpu . _callbackInterface . _write32 ( address , oldRegRn ) ;
}
else
{
UInt32 value = i switch
{
8 = > cpu . Reg8_usr ,
9 = > cpu . Reg9_usr ,
10 = > cpu . Reg10_usr ,
11 = > cpu . Reg11_usr ,
12 = > cpu . Reg12_usr ,
13 = > cpu . Reg13_usr ,
14 = > cpu . Reg14_usr ,
_ = > Unsafe . Add ( ref regDataRef , i ) ,
} ;
cpu . _callbackInterface . _write32 ( address , value ) ;
}
address + = 4 ;
}
}
if ( ( ( registerList > > 15 ) & 1 ) = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( address , regPC + 4 ) ;
}
2024-08-15 13:19:43 +08:00
UInt32 n = ( UInt32 ) MyBitOperations . PopCount ( registerList ) ;
2024-08-14 16:02:39 +08:00
return n + 1 ;
}
}
private static UInt64 STR ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
UInt32 data = ( rd = = PC ) ? ( regPC + 4 ) : regRd ;
UInt32 address = GetAddress ( cpu , instruction ) ;
cpu . _callbackInterface . _write32 ( address , data ) ;
return 2 ;
}
private static UInt64 STRB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
UInt32 data = ( rd = = PC ) ? ( regPC + 4 ) : regRd ;
UInt32 address = GetAddress ( cpu , instruction ) ;
cpu . _callbackInterface . _write8 ( address , ( Byte ) data ) ;
return 2 ;
}
private static UInt64 STRH ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
UInt32 data = ( rd = = PC ) ? ( regPC + 4 ) : regRd ;
UInt32 address = GetAddress_Misc ( cpu , instruction ) ;
cpu . _callbackInterface . _write16 ( address , ( UInt16 ) data ) ;
return 2 ;
}
private static UInt64 SUB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , _ ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt64 result = ( UInt64 ) leftOperand - ( UInt64 ) rightOperand ;
SetReg ( cpu , rd , ( UInt32 ) result ) ;
if ( s = = 1 )
{
if ( rd = = PC )
{
cpu . SetCPSR ( cpu . SPSR ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRd = ref Unsafe . Add ( ref regDataRef , ( int ) rd ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRd > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( regRd = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , Not ( BorrowFrom ( result ) ) ) ;
cpu . SetFlag ( Flag . V , OverflowFrom_Subtraction ( leftOperand , rightOperand , regRd ) ) ;
return shiftRs ? 2 u : 1 u ;
}
}
else
{
return ( shiftRs ? 2 u : 1 u ) + ( ( rd = = PC ) ? 2 u : 0 u ) ;
}
}
private static UInt64 SWI ( CPU_Core cpu , UInt32 instruction )
{
return cpu . _callbackInterface . _handleSWI ( ) ;
}
private static UInt64 SWP ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
2024-08-15 13:19:43 +08:00
UInt32 temp = MyBitOperations . RotateRight ( cpu . _callbackInterface . _read32 ( regRn ) , ( int ) ( 8 * ( regRn & 0 b11 ) ) ) ;
2024-08-14 16:02:39 +08:00
cpu . _callbackInterface . _write32 ( regRn , regRm ) ;
SetReg ( cpu , rd , temp ) ;
return 4 ;
}
private static UInt64 SWPB ( CPU_Core cpu , UInt32 instruction )
{
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
Byte temp = cpu . _callbackInterface . _read8 ( regRn ) ;
cpu . _callbackInterface . _write8 ( regRn , ( Byte ) regRm ) ;
SetReg ( cpu , rd , temp ) ;
return 4 ;
}
private static UInt64 TEQ ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt32 aluOut = leftOperand ^ rightOperand ;
if ( rd = = PC )
{
if ( ( cpu . CPSR & ModeMask ) = = UserMode )
cpu . CPSR = ( cpu . CPSR & ~ 0xf000 _0000 ) | ( aluOut & 0xf000 _0000 ) ;
else
cpu . SetCPSR ( ( cpu . CPSR & ~ 0xf000 _00c3 ) | ( aluOut & 0xf000 _0003 ) | ( ( ( aluOut > > 26 ) & 0 b11 ) < < 6 ) ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
cpu . SetFlag ( Flag . N , aluOut > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( aluOut = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
private static UInt64 TST ( CPU_Core cpu , UInt32 instruction )
{
UInt32 i = ( instruction > > 25 ) & 1 ;
UInt32 rn = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rd = ( instruction > > 12 ) & 0 b1111 ;
UInt32 r = ( instruction > > 4 ) & 1 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRn = ref Unsafe . Add ( ref regDataRef , ( int ) rn ) ;
ref UInt32 regPC = ref Unsafe . Add ( ref regDataRef , ( int ) PC ) ;
2024-08-14 16:02:39 +08:00
( UInt32 shifterOperand , UInt32 shifterCarryOut ) = GetShifterOperand ( cpu , instruction ) ;
bool shiftRs = ( i = = 0 ) & & ( r = = 1 ) ;
UInt32 leftOperand = ( ( rn = = PC ) & & shiftRs ) ? ( regPC + 4 ) : regRn ;
UInt32 rightOperand = shifterOperand ;
UInt32 aluOut = leftOperand & rightOperand ;
if ( rd = = PC )
{
if ( ( cpu . CPSR & ModeMask ) = = UserMode )
cpu . CPSR = ( cpu . CPSR & ~ 0xf000 _0000 ) | ( aluOut & 0xf000 _0000 ) ;
else
cpu . SetCPSR ( ( cpu . CPSR & ~ 0xf000 _00c3 ) | ( aluOut & 0xf000 _0003 ) | ( ( ( aluOut > > 26 ) & 0 b11 ) < < 6 ) ) ;
return shiftRs ? 4 u : 3 u ;
}
else
{
cpu . SetFlag ( Flag . N , aluOut > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( aluOut = = 0 ) ? 1 u : 0 u ) ;
cpu . SetFlag ( Flag . C , shifterCarryOut ) ;
return shiftRs ? 2 u : 1 u ;
}
}
private static UInt64 UMLAL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rdHi = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rdLo = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRdHi = ref Unsafe . Add ( ref regDataRef , ( int ) rdHi ) ;
ref UInt32 regRdLo = ref Unsafe . Add ( ref regDataRef , ( int ) rdLo ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
UInt64 result = ( UInt64 ) regRm * ( UInt64 ) regRs ;
UInt64 resultLo = ( UInt64 ) ( UInt32 ) result + ( UInt64 ) regRdLo ;
UInt32 resultHi = ( UInt32 ) ( result > > 32 ) + regRdHi + CarryFrom ( resultLo ) ;
SetReg ( cpu , rdLo , ( UInt32 ) resultLo ) ;
SetReg ( cpu , rdHi , resultHi ) ;
if ( s = = 1 )
{
cpu . SetFlag ( Flag . N , regRdHi > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( ( regRdHi = = 0 ) & & ( regRdLo = = 0 ) ) ? 1 u : 0 u ) ;
}
return m + 3 ;
}
private static UInt64 UMULL ( CPU_Core cpu , UInt32 instruction )
{
UInt32 s = ( instruction > > 20 ) & 1 ;
UInt32 rdHi = ( instruction > > 16 ) & 0 b1111 ;
UInt32 rdLo = ( instruction > > 12 ) & 0 b1111 ;
UInt32 rs = ( instruction > > 8 ) & 0 b1111 ;
UInt32 rm = instruction & 0 b1111 ;
2024-08-15 13:19:43 +08:00
ref UInt32 regDataRef = ref MyUnSafeCommon . GetArrayDataReference ( cpu . Reg ) ;
ref UInt32 regRs = ref Unsafe . Add ( ref regDataRef , ( int ) rs ) ;
ref UInt32 regRm = ref Unsafe . Add ( ref regDataRef , ( int ) rm ) ;
2024-08-14 16:02:39 +08:00
UInt64 m = ComputeMultiplicationCycleCount ( regRm , regRs ) ;
UInt64 result = ( UInt64 ) regRm * ( UInt64 ) regRs ;
SetReg ( cpu , rdLo , ( UInt32 ) result ) ;
SetReg ( cpu , rdHi , ( UInt32 ) ( result > > 32 ) ) ;
if ( s = = 1 )
{
2024-08-15 13:19:43 +08:00
ref UInt32 regRdHi = ref Unsafe . Add ( ref regDataRef , ( int ) rdHi ) ;
ref UInt32 regRdLo = ref Unsafe . Add ( ref regDataRef , ( int ) rdLo ) ;
2024-08-14 16:02:39 +08:00
cpu . SetFlag ( Flag . N , regRdHi > > 31 ) ;
cpu . SetFlag ( Flag . Z , ( ( regRdHi = = 0 ) & & ( regRdLo = = 0 ) ) ? 1 u : 0 u ) ;
}
return m + 2 ;
}
}
}