mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-14 17:00:17 +00:00
T16: Implement IT
This commit is contained in:
parent
09c84d6e91
commit
b6078d2c00
7 changed files with 79 additions and 4 deletions
|
@ -195,21 +195,31 @@ namespace ARMeilleure.Decoders
|
|||
ulong limitAddress)
|
||||
{
|
||||
ulong address = block.Address;
|
||||
int inITBlock = 0;
|
||||
|
||||
OpCode opCode;
|
||||
|
||||
do
|
||||
{
|
||||
if (address >= limitAddress)
|
||||
if (address >= limitAddress && inITBlock == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
opCode = DecodeOpCode(memory, address, mode);
|
||||
opCode = DecodeOpCode(memory, address, mode, inITBlock > 0);
|
||||
|
||||
block.OpCodes.Add(opCode);
|
||||
|
||||
address += (ulong)opCode.OpCodeSizeInBytes;
|
||||
|
||||
if (opCode is OpCodeT16IfThen it)
|
||||
{
|
||||
inITBlock = it.IfThenBlockSize;
|
||||
}
|
||||
else if (inITBlock > 0)
|
||||
{
|
||||
inITBlock--;
|
||||
}
|
||||
}
|
||||
while (!(IsBranch(opCode) || IsException(opCode)));
|
||||
|
||||
|
@ -315,7 +325,7 @@ namespace ARMeilleure.Decoders
|
|||
opCode.Instruction.Name == InstName.Und;
|
||||
}
|
||||
|
||||
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode, bool inITBlock = false)
|
||||
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode, bool inITBlock)
|
||||
{
|
||||
int opCode = memory.Read<int>(address);
|
||||
|
||||
|
|
34
ARMeilleure/Decoders/OpCodeT16IfThen.cs
Normal file
34
ARMeilleure/Decoders/OpCodeT16IfThen.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeT16IfThen : OpCodeT16
|
||||
{
|
||||
public Condition[] IfThenBlockConds { get; }
|
||||
|
||||
public int IfThenBlockSize { get { return IfThenBlockConds.Length; } }
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode, bool inITBlock) => new OpCodeT16IfThen(inst, address, opCode, inITBlock);
|
||||
|
||||
public OpCodeT16IfThen(InstDescriptor inst, ulong address, int opCode, bool inITBlock) : base(inst, address, opCode, inITBlock)
|
||||
{
|
||||
List<Condition> conds = new();
|
||||
|
||||
int cond = (opCode >> 4) & 0xf;
|
||||
int mask = opCode & 0xf;
|
||||
|
||||
conds.Add((Condition)cond);
|
||||
|
||||
while ((mask & 7) != 0)
|
||||
{
|
||||
int newLsb = (mask >> 3) & 1;
|
||||
cond = (cond & 0xe) | newLsb;
|
||||
mask <<= 1;
|
||||
conds.Add((Condition)cond);
|
||||
}
|
||||
|
||||
IfThenBlockConds = conds.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1037,12 +1037,13 @@ namespace ARMeilleure.Decoders
|
|||
SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
|
||||
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
|
||||
SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create);
|
||||
SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create);
|
||||
SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
|
||||
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
|
||||
SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create);
|
||||
SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create);
|
||||
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
||||
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
|
||||
|
|
|
@ -100,5 +100,12 @@ namespace ARMeilleure.Instructions
|
|||
context.BranchIfFalse(lblTarget, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void It(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeT16IfThen op = (OpCodeT16IfThen)context.CurrOp;
|
||||
|
||||
context.IfThenBlockState = op.IfThenBlockConds;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ namespace ARMeilleure.Instructions
|
|||
Extr,
|
||||
Hint,
|
||||
Isb,
|
||||
It,
|
||||
Ldar,
|
||||
Ldaxp,
|
||||
Ldaxr,
|
||||
|
|
|
@ -9,6 +9,7 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -54,6 +55,10 @@ namespace ARMeilleure.Translation
|
|||
public bool HighCq { get; }
|
||||
public Aarch32Mode Mode { get; }
|
||||
|
||||
public bool IsInIfThenBlock { get { return IfThenBlockState.Length > 0; } }
|
||||
public Condition CurrentIfThenBlockCond { get { return IfThenBlockState[0]; } }
|
||||
public Condition[] IfThenBlockState { get; set; }
|
||||
|
||||
public ArmEmitterContext(
|
||||
IMemoryManager memory,
|
||||
EntryTable<uint> countTable,
|
||||
|
@ -196,5 +201,13 @@ namespace ARMeilleure.Translation
|
|||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void AdvanceIfThenBlockState()
|
||||
{
|
||||
if (IsInIfThenBlock)
|
||||
{
|
||||
IfThenBlockState = IfThenBlockState.Skip(1).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -380,6 +380,15 @@ namespace ARMeilleure.Translation
|
|||
|
||||
Operand lblPredicateSkip = default;
|
||||
|
||||
if (context.IsInIfThenBlock)
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert());
|
||||
|
||||
context.AdvanceIfThenBlockState();
|
||||
}
|
||||
|
||||
if (opCode is OpCode32 op && op.Cond < Condition.Al)
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
|
|
Loading…
Reference in a new issue