mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-14 20:50:18 +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 limitAddress)
|
||||||
{
|
{
|
||||||
ulong address = block.Address;
|
ulong address = block.Address;
|
||||||
|
int inITBlock = 0;
|
||||||
|
|
||||||
OpCode opCode;
|
OpCode opCode;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (address >= limitAddress)
|
if (address >= limitAddress && inITBlock == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
opCode = DecodeOpCode(memory, address, mode);
|
opCode = DecodeOpCode(memory, address, mode, inITBlock > 0);
|
||||||
|
|
||||||
block.OpCodes.Add(opCode);
|
block.OpCodes.Add(opCode);
|
||||||
|
|
||||||
address += (ulong)opCode.OpCodeSizeInBytes;
|
address += (ulong)opCode.OpCodeSizeInBytes;
|
||||||
|
|
||||||
|
if (opCode is OpCodeT16IfThen it)
|
||||||
|
{
|
||||||
|
inITBlock = it.IfThenBlockSize;
|
||||||
|
}
|
||||||
|
else if (inITBlock > 0)
|
||||||
|
{
|
||||||
|
inITBlock--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (!(IsBranch(opCode) || IsException(opCode)));
|
while (!(IsBranch(opCode) || IsException(opCode)));
|
||||||
|
|
||||||
|
@ -315,7 +325,7 @@ namespace ARMeilleure.Decoders
|
||||||
opCode.Instruction.Name == InstName.Und;
|
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);
|
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("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
|
||||||
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
|
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
|
||||||
SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.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("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
|
||||||
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
|
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
|
||||||
SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create);
|
SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create);
|
||||||
SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create);
|
SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create);
|
||||||
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
|
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
||||||
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
|
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
|
||||||
|
|
|
@ -100,5 +100,12 @@ namespace ARMeilleure.Instructions
|
||||||
context.BranchIfFalse(lblTarget, value);
|
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,
|
Extr,
|
||||||
Hint,
|
Hint,
|
||||||
Isb,
|
Isb,
|
||||||
|
It,
|
||||||
Ldar,
|
Ldar,
|
||||||
Ldaxp,
|
Ldaxp,
|
||||||
Ldaxr,
|
Ldaxr,
|
||||||
|
|
|
@ -9,6 +9,7 @@ using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
@ -54,6 +55,10 @@ namespace ARMeilleure.Translation
|
||||||
public bool HighCq { get; }
|
public bool HighCq { get; }
|
||||||
public Aarch32Mode Mode { 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(
|
public ArmEmitterContext(
|
||||||
IMemoryManager memory,
|
IMemoryManager memory,
|
||||||
EntryTable<uint> countTable,
|
EntryTable<uint> countTable,
|
||||||
|
@ -196,5 +201,13 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AdvanceIfThenBlockState()
|
||||||
|
{
|
||||||
|
if (IsInIfThenBlock)
|
||||||
|
{
|
||||||
|
IfThenBlockState = IfThenBlockState.Skip(1).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -380,6 +380,15 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand lblPredicateSkip = default;
|
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)
|
if (opCode is OpCode32 op && op.Cond < Condition.Al)
|
||||||
{
|
{
|
||||||
lblPredicateSkip = Label();
|
lblPredicateSkip = Label();
|
||||||
|
|
Loading…
Reference in a new issue