forked from Mirror/Ryujinx
129 lines
3.6 KiB
C#
129 lines
3.6 KiB
C#
|
using ARMeilleure.Decoders;
|
||
|
using ARMeilleure.IntermediateRepresentation;
|
||
|
using ARMeilleure.State;
|
||
|
using ARMeilleure.Translation;
|
||
|
|
||
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||
|
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||
|
|
||
|
namespace ARMeilleure.Instructions
|
||
|
{
|
||
|
static partial class InstEmit32
|
||
|
{
|
||
|
public static void Add(ArmEmitterContext context)
|
||
|
{
|
||
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||
|
|
||
|
Operand n = GetAluN(context);
|
||
|
Operand m = GetAluM(context, setCarry: false);
|
||
|
|
||
|
Operand res = context.Add(n, m);
|
||
|
|
||
|
if (op.SetFlags)
|
||
|
{
|
||
|
EmitNZFlagsCheck(context, res);
|
||
|
|
||
|
EmitAddsCCheck(context, n, res);
|
||
|
EmitAddsVCheck(context, n, m, res);
|
||
|
}
|
||
|
|
||
|
EmitAluStore(context, res);
|
||
|
}
|
||
|
|
||
|
public static void Cmp(ArmEmitterContext context)
|
||
|
{
|
||
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||
|
|
||
|
Operand n = GetAluN(context);
|
||
|
Operand m = GetAluM(context, setCarry: false);
|
||
|
|
||
|
Operand res = context.Subtract(n, m);
|
||
|
|
||
|
EmitNZFlagsCheck(context, res);
|
||
|
|
||
|
EmitSubsCCheck(context, n, res);
|
||
|
EmitSubsVCheck(context, n, m, res);
|
||
|
}
|
||
|
|
||
|
public static void Mov(ArmEmitterContext context)
|
||
|
{
|
||
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||
|
|
||
|
Operand m = GetAluM(context);
|
||
|
|
||
|
if (op.SetFlags)
|
||
|
{
|
||
|
EmitNZFlagsCheck(context, m);
|
||
|
}
|
||
|
|
||
|
EmitAluStore(context, m);
|
||
|
}
|
||
|
|
||
|
public static void Sub(ArmEmitterContext context)
|
||
|
{
|
||
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||
|
|
||
|
Operand n = GetAluN(context);
|
||
|
Operand m = GetAluM(context, setCarry: false);
|
||
|
|
||
|
Operand res = context.Subtract(n, m);
|
||
|
|
||
|
if (op.SetFlags)
|
||
|
{
|
||
|
EmitNZFlagsCheck(context, res);
|
||
|
|
||
|
EmitSubsCCheck(context, n, res);
|
||
|
EmitSubsVCheck(context, n, m, res);
|
||
|
}
|
||
|
|
||
|
EmitAluStore(context, res);
|
||
|
}
|
||
|
|
||
|
private static void EmitAluStore(ArmEmitterContext context, Operand value)
|
||
|
{
|
||
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||
|
|
||
|
if (op.Rd == RegisterAlias.Aarch32Pc)
|
||
|
{
|
||
|
if (op.SetFlags)
|
||
|
{
|
||
|
// TODO: Load SPSR etc.
|
||
|
Operand isThumb = GetFlag(PState.TFlag);
|
||
|
|
||
|
Operand lblThumb = Label();
|
||
|
|
||
|
context.BranchIfTrue(lblThumb, isThumb);
|
||
|
|
||
|
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~3))));
|
||
|
|
||
|
context.MarkLabel(lblThumb);
|
||
|
|
||
|
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EmitAluWritePc(context, value);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetIntA32(context, op.Rd, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void EmitAluWritePc(ArmEmitterContext context, Operand value)
|
||
|
{
|
||
|
context.StoreToContext();
|
||
|
|
||
|
if (IsThumb(context.CurrOp))
|
||
|
{
|
||
|
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EmitBxWritePc(context, value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|