T16: Implement IT

This commit is contained in:
merry 2022-02-11 22:58:13 +00:00
parent 09c84d6e91
commit b6078d2c00
7 changed files with 79 additions and 4 deletions

View file

@ -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);

View 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();
}
}
}

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -48,6 +48,7 @@ namespace ARMeilleure.Instructions
Extr,
Hint,
Isb,
It,
Ldar,
Ldaxp,
Ldaxr,

View file

@ -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();
}
}
}
}

View file

@ -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();