Add ARM32 support on the translator (#561)
* Remove ARM32 interpreter and add ARM32 support on the translator * Nits. * Rename Cond -> Condition * Align code again * Rename Data to Alu * Enable ARM32 support and handle undefined instructions * Use the IsThumb method to check if its a thumb opcode * Remove another 32-bits check
This commit is contained in:
parent
72157e03eb
commit
36b9ab0e48
57 changed files with 1274 additions and 495 deletions
|
@ -19,20 +19,20 @@ namespace ChocolArm64.Decoders
|
|||
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
|
||||
}
|
||||
|
||||
public static Block DecodeBasicBlock(CpuThreadState state, MemoryManager memory, long start)
|
||||
public static Block DecodeBasicBlock(MemoryManager memory, long start, ExecutionMode mode)
|
||||
{
|
||||
Block block = new Block(start);
|
||||
|
||||
FillBlock(state, memory, block);
|
||||
FillBlock(memory, mode, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
public static Block DecodeSubroutine(
|
||||
TranslatorCache cache,
|
||||
CpuThreadState state,
|
||||
MemoryManager memory,
|
||||
long start)
|
||||
long start,
|
||||
ExecutionMode mode)
|
||||
{
|
||||
Dictionary<long, Block> visited = new Dictionary<long, Block>();
|
||||
Dictionary<long, Block> visitedEnd = new Dictionary<long, Block>();
|
||||
|
@ -59,7 +59,7 @@ namespace ChocolArm64.Decoders
|
|||
{
|
||||
Block current = blocks.Dequeue();
|
||||
|
||||
FillBlock(state, memory, current);
|
||||
FillBlock(memory, mode, current);
|
||||
|
||||
//Set child blocks. "Branch" is the block the branch instruction
|
||||
//points to (when taken), "Next" is the block at the next address,
|
||||
|
@ -71,7 +71,7 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
OpCode64 lastOp = current.GetLastOp();
|
||||
|
||||
if (lastOp is OpCodeBImm64 op)
|
||||
if (lastOp is IOpCodeBImm op)
|
||||
{
|
||||
if (op.Emitter == InstEmit.Bl)
|
||||
{
|
||||
|
@ -83,8 +83,7 @@ namespace ChocolArm64.Decoders
|
|||
}
|
||||
}
|
||||
|
||||
if (!((lastOp is OpCodeBImmAl64) ||
|
||||
(lastOp is OpCodeBReg64)) || hasCachedSub)
|
||||
if (!IsUnconditionalBranch(lastOp) || hasCachedSub)
|
||||
{
|
||||
current.Next = Enqueue(current.EndPosition);
|
||||
}
|
||||
|
@ -121,7 +120,7 @@ namespace ChocolArm64.Decoders
|
|||
return entry;
|
||||
}
|
||||
|
||||
private static void FillBlock(CpuThreadState state, MemoryManager memory, Block block)
|
||||
private static void FillBlock(MemoryManager memory, ExecutionMode mode, Block block)
|
||||
{
|
||||
long position = block.Position;
|
||||
|
||||
|
@ -129,13 +128,11 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
do
|
||||
{
|
||||
//TODO: This needs to be changed to support both AArch32 and AArch64,
|
||||
//once JIT support is introduced on AArch32 aswell.
|
||||
opCode = DecodeOpCode(state, memory, position);
|
||||
opCode = DecodeOpCode(memory, position, mode);
|
||||
|
||||
block.OpCodes.Add(opCode);
|
||||
|
||||
position += 4;
|
||||
position += opCode.OpCodeSizeInBytes;
|
||||
}
|
||||
while (!(IsBranch(opCode) || IsException(opCode)));
|
||||
|
||||
|
@ -145,7 +142,35 @@ namespace ChocolArm64.Decoders
|
|||
private static bool IsBranch(OpCode64 opCode)
|
||||
{
|
||||
return opCode is OpCodeBImm64 ||
|
||||
opCode is OpCodeBReg64;
|
||||
opCode is OpCodeBReg64 || IsAarch32Branch(opCode);
|
||||
}
|
||||
|
||||
private static bool IsUnconditionalBranch(OpCode64 opCode)
|
||||
{
|
||||
return opCode is OpCodeBImmAl64 ||
|
||||
opCode is OpCodeBReg64 || IsAarch32UnconditionalBranch(opCode);
|
||||
}
|
||||
|
||||
private static bool IsAarch32UnconditionalBranch(OpCode64 opCode)
|
||||
{
|
||||
if (!(opCode is OpCode32 op))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Note: On ARM32, most instructions have conditional execution,
|
||||
//so there's no "Always" (unconditional) branch like on ARM64.
|
||||
//We need to check if the condition is "Always" instead.
|
||||
return IsAarch32Branch(op) && op.Cond >= Condition.Al;
|
||||
}
|
||||
|
||||
private static bool IsAarch32Branch(OpCode64 opCode)
|
||||
{
|
||||
//Note: On ARM32, most ALU operations can write to R15 (PC),
|
||||
//so we must consider such operations as a branch in potential aswell.
|
||||
return opCode is IOpCodeBImm32 ||
|
||||
opCode is IOpCodeBReg32 ||
|
||||
(opCode is IOpCodeAlu32 op && op.Rd == RegisterAlias.Aarch32Pc);
|
||||
}
|
||||
|
||||
private static bool IsException(OpCode64 opCode)
|
||||
|
@ -155,20 +180,26 @@ namespace ChocolArm64.Decoders
|
|||
opCode.Emitter == InstEmit.Und;
|
||||
}
|
||||
|
||||
public static OpCode64 DecodeOpCode(CpuThreadState state, MemoryManager memory, long position)
|
||||
public static OpCode64 DecodeOpCode(MemoryManager memory, long position, ExecutionMode mode)
|
||||
{
|
||||
int opCode = memory.ReadInt32(position);
|
||||
|
||||
Inst inst;
|
||||
|
||||
if (state.ExecutionMode == ExecutionMode.AArch64)
|
||||
if (mode == ExecutionMode.Aarch64)
|
||||
{
|
||||
inst = OpCodeTable.GetInstA64(opCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Thumb support.
|
||||
inst = OpCodeTable.GetInstA32(opCode);
|
||||
if (mode == ExecutionMode.Aarch32Arm)
|
||||
{
|
||||
inst = OpCodeTable.GetInstA32(opCode);
|
||||
}
|
||||
else /* if (mode == ExecutionMode.Aarch32Thumb) */
|
||||
{
|
||||
inst = OpCodeTable.GetInstT32(opCode);
|
||||
}
|
||||
}
|
||||
|
||||
OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue