Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
814f75142e |
@@ -726,7 +726,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -774,7 +774,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -900,7 +900,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -948,7 +948,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1633,37 +1633,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Frinti_S(ArmEmitterContext context)
|
public static void Frinti_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (op.Size == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (op.Size == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frinti_V(ArmEmitterContext context)
|
public static void Frinti_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
|
||||||
|
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (sizeF == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (sizeF == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1759,37 +1739,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Frintx_S(ArmEmitterContext context)
|
public static void Frintx_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (op.Size == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (op.Size == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frintx_V(ArmEmitterContext context)
|
public static void Frintx_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
|
||||||
|
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (sizeF == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (sizeF == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||||
@@ -178,37 +177,20 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
||||||
{
|
{
|
||||||
Operand one = Const(1);
|
|
||||||
if (zero)
|
if (zero)
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) =>
|
EmitVectorUnaryOpF32(context, (m) =>
|
||||||
{
|
{
|
||||||
OperandType type = m.Type;
|
Operand zeroOp = m.Type == OperandType.FP64 ? ConstF(0.0d) : ConstF(0.0f);
|
||||||
|
|
||||||
if (type == OperandType.FP64)
|
return EmitSoftFloatCallDefaultFpscr(context, name, m, zeroOp);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat64).GetMethod(name), m, ConstF(0.0d), one);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(name), m, ConstF(0.0f), one);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorBinaryOpF32(context, (n, m) =>
|
EmitVectorBinaryOpF32(context, (n, m) =>
|
||||||
{
|
{
|
||||||
OperandType type = n.Type;
|
return EmitSoftFloatCallDefaultFpscr(context, name, n, m);
|
||||||
|
|
||||||
if (type == OperandType.FP64)
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat64).GetMethod(name), n, m, one);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(name), n, m, one);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,11 +339,7 @@ namespace ARMeilleure.Instructions
|
|||||||
me = ExtractScalar(context, type, op.Vm);
|
me = ExtractScalar(context, type, op.Vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodInfo info = sizeF != 0
|
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
|
||||||
? typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))
|
|
||||||
: typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare));
|
|
||||||
|
|
||||||
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
|
|
||||||
|
|
||||||
EmitSetFpscrNzcv(context, nzcv);
|
EmitSetFpscrNzcv(context, nzcv);
|
||||||
}
|
}
|
||||||
|
@@ -76,7 +76,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.ZeroExtend16(OperandType.I64, res);
|
res = context.ZeroExtend16(OperandType.I64, res);
|
||||||
|
|
||||||
@@ -98,7 +100,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||||
}
|
}
|
||||||
@@ -120,7 +124,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
|
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.ZeroExtend16(OperandType.I64, res);
|
res = context.ZeroExtend16(OperandType.I64, res);
|
||||||
|
|
||||||
@@ -143,7 +149,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||||
}
|
}
|
||||||
@@ -224,7 +232,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.VectorInsert(res, e, index);
|
res = context.VectorInsert(res, e, index);
|
||||||
}
|
}
|
||||||
@@ -333,7 +343,9 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (sizeF == 0)
|
if (sizeF == 0)
|
||||||
{
|
{
|
||||||
|
context.StoreToContext();
|
||||||
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
e = context.ZeroExtend16(OperandType.I64, e);
|
e = context.ZeroExtend16(OperandType.I64, e);
|
||||||
|
|
||||||
|
@@ -161,34 +161,15 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
||||||
|
|
||||||
Operand asInteger;
|
|
||||||
|
|
||||||
// TODO: Fast Path.
|
// TODO: Fast Path.
|
||||||
if (roundWithFpscr)
|
if (roundWithFpscr)
|
||||||
{
|
{
|
||||||
MethodInfo info;
|
toConvert = EmitRoundByRMode(context, toConvert);
|
||||||
|
|
||||||
if (floatSize == OperandType.FP64)
|
|
||||||
{
|
|
||||||
info = unsigned
|
|
||||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))
|
|
||||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info = unsigned
|
|
||||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))
|
|
||||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32));
|
|
||||||
}
|
|
||||||
|
|
||||||
asInteger = context.Call(info, toConvert);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Round towards zero.
|
|
||||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round towards zero.
|
||||||
|
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||||
|
|
||||||
InsertScalar(context, op.Vd, asInteger);
|
InsertScalar(context, op.Vd, asInteger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,9 +252,7 @@ namespace ARMeilleure.Instructions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand asInteger;
|
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||||
|
|
||||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
|
||||||
|
|
||||||
InsertScalar(context, op.Vd, asInteger);
|
InsertScalar(context, op.Vd, asInteger);
|
||||||
}
|
}
|
||||||
@@ -399,15 +378,9 @@ namespace ARMeilleure.Instructions
|
|||||||
// VRINTX (floating-point).
|
// VRINTX (floating-point).
|
||||||
public static void Vrintx_S(ArmEmitterContext context)
|
public static void Vrintx_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
|
||||||
|
|
||||||
bool doubleSize = (op.Size & 1) == 1;
|
|
||||||
string methodName = doubleSize ? nameof(SoftFallback.Round) : nameof(SoftFallback.RoundF);
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF32(context, (op1) =>
|
EmitScalarUnaryOpF32(context, (op1) =>
|
||||||
{
|
{
|
||||||
MethodInfo info = typeof(SoftFallback).GetMethod(methodName);
|
return EmitRoundByRMode(context, op1);
|
||||||
return context.Call(info, op1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -361,6 +361,54 @@ namespace ARMeilleure.Instructions
|
|||||||
return context.Call(info, n, Const((int)roundMode));
|
return context.Call(info, n, Const((int)roundMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand EmitGetRoundingMode(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
Operand rMode = context.ShiftLeft(GetFpFlag(FPState.RMode1Flag), Const(1));
|
||||||
|
rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
|
||||||
|
|
||||||
|
return rMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||||
|
{
|
||||||
|
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
||||||
|
|
||||||
|
Operand lbl1 = Label();
|
||||||
|
Operand lbl2 = Label();
|
||||||
|
Operand lbl3 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand rN = Const((int)FPRoundingMode.ToNearest);
|
||||||
|
Operand rP = Const((int)FPRoundingMode.TowardsPlusInfinity);
|
||||||
|
Operand rM = Const((int)FPRoundingMode.TowardsMinusInfinity);
|
||||||
|
|
||||||
|
Operand res = context.AllocateLocal(op.Type);
|
||||||
|
|
||||||
|
Operand rMode = EmitGetRoundingMode(context);
|
||||||
|
|
||||||
|
context.BranchIf(lbl1, rMode, rN, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitRoundMathCall(context, MidpointRounding.ToEven, op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl1);
|
||||||
|
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl2);
|
||||||
|
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl3);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
||||||
{
|
{
|
||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
@@ -369,7 +417,11 @@ namespace ARMeilleure.Instructions
|
|||||||
? typeof(SoftFloat32).GetMethod(name)
|
? typeof(SoftFloat32).GetMethod(name)
|
||||||
: typeof(SoftFloat64).GetMethod(name);
|
: typeof(SoftFloat64).GetMethod(name);
|
||||||
|
|
||||||
return context.Call(info, callArgs);
|
context.StoreToContext();
|
||||||
|
Operand res = context.Call(info, callArgs);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
||||||
@@ -1269,7 +1321,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
|
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
|
||||||
{
|
{
|
||||||
isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
isTrue = GetFpFlag(FPState.FzFlag);
|
||||||
|
|
||||||
Operand lblTrue = Label();
|
Operand lblTrue = Label();
|
||||||
context.BranchIfFalse(lblTrue, isTrue);
|
context.BranchIfFalse(lblTrue, isTrue);
|
||||||
@@ -1281,9 +1333,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
|
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
|
||||||
{
|
{
|
||||||
isTrue = isTrue == default
|
isTrue = isTrue == default ? GetFpFlag(FPState.FzFlag) : isTrue;
|
||||||
? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)))
|
|
||||||
: isTrue;
|
|
||||||
|
|
||||||
Operand lblTrue = Label();
|
Operand lblTrue = Label();
|
||||||
context.BranchIfFalse(lblTrue, isTrue);
|
context.BranchIfFalse(lblTrue, isTrue);
|
||||||
@@ -1552,13 +1602,13 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
|
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
|
||||||
context.Copy(res, maxT);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, minT);
|
context.Copy(res, minT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1583,7 +1633,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
|
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
|
||||||
context.Copy(res, maxT);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1610,13 +1660,13 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
|
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
|
||||||
context.Copy(res, maxT);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, minT);
|
context.Copy(res, minT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1641,7 +1691,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
|
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
|
||||||
context.Copy(res, maxT);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1663,7 +1713,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
|
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1691,7 +1741,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1713,7 +1763,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, maxUL);
|
context.Copy(res, maxUL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1741,7 +1791,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1763,7 +1813,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, zeroL);
|
context.Copy(res, zeroL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1790,19 +1840,19 @@ namespace ARMeilleure.Instructions
|
|||||||
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
|
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
|
||||||
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
|
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl2);
|
context.MarkLabel(lbl2);
|
||||||
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
|
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1828,14 +1878,14 @@ namespace ARMeilleure.Instructions
|
|||||||
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
|
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
|
||||||
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, maxUL);
|
context.Copy(res, maxUL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
|
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
|
||||||
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, zeroL);
|
context.Copy(res, zeroL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
|
@@ -1181,7 +1181,11 @@ namespace ARMeilleure.Instructions
|
|||||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||||
callArgs[callArgs.Length - 1] = Const(1);
|
callArgs[callArgs.Length - 1] = Const(1);
|
||||||
|
|
||||||
return context.Call(info, callArgs);
|
context.StoreToContext();
|
||||||
|
Operand res = context.Call(info, callArgs);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -378,7 +379,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
|
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
|
||||||
|
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
|
|
||||||
context.MarkLabel(lblNoSat);
|
context.MarkLabel(lblNoSat);
|
||||||
|
|
||||||
|
@@ -31,8 +31,8 @@ namespace ARMeilleure.Instructions
|
|||||||
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
||||||
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
||||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)); break;
|
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
|
||||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)); break;
|
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
|
||||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
||||||
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
|
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
|
||||||
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
||||||
@@ -53,9 +53,9 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
switch (GetPackedId(op))
|
switch (GetPackedId(op))
|
||||||
{
|
{
|
||||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)); break;
|
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
|
||||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)); break;
|
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
|
||||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
||||||
|
|
||||||
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||||
@@ -121,39 +121,91 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
Operand nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||||
|
|
||||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
SetIntOrZR(context, op.Rt, nzcv);
|
||||||
|
}
|
||||||
|
|
||||||
SetIntOrZR(context, op.Rt, nzcvSh);
|
private static void EmitGetFpcr(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
|
Operand fpcr = Const(0);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntOrZR(context, op.Rt, fpcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitGetFpsr(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
|
Operand fpsr = Const(0);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntOrZR(context, op.Rt, fpsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSetNzcv(ArmEmitterContext context)
|
private static void EmitSetNzcv(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand t = GetIntOrZR(context, op.Rt);
|
Operand nzcv = GetIntOrZR(context, op.Rt);
|
||||||
t = context.ConvertI64ToI32(t);
|
nzcv = context.ConvertI64ToI32(nzcv);
|
||||||
|
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
|
||||||
v = context.BitwiseAnd (v, Const(1));
|
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
|
||||||
|
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
|
||||||
|
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
|
||||||
|
}
|
||||||
|
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
private static void EmitSetFpcr(ArmEmitterContext context)
|
||||||
c = context.BitwiseAnd (c, Const(1));
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
Operand fpcr = GetIntOrZR(context, op.Rt);
|
||||||
z = context.BitwiseAnd (z, Const(1));
|
fpcr = context.ConvertI64ToI32(fpcr);
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
n = context.BitwiseAnd (n, Const(1));
|
{
|
||||||
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetFlag(context, PState.VFlag, v);
|
private static void EmitSetFpsr(ArmEmitterContext context)
|
||||||
SetFlag(context, PState.CFlag, c);
|
{
|
||||||
SetFlag(context, PState.ZFlag, z);
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
SetFlag(context, PState.NFlag, n);
|
|
||||||
|
Operand fpsr = GetIntOrZR(context, op.Rt);
|
||||||
|
fpsr = context.ConvertI64ToI32(fpsr);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||||
|
{
|
||||||
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -169,14 +169,11 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||||
Operand qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
|
||||||
|
|
||||||
Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
|
||||||
spsr = context.BitwiseOr(spsr, qSh);
|
|
||||||
|
|
||||||
// TODO: Remaining flags.
|
// TODO: Remaining flags.
|
||||||
|
|
||||||
@@ -200,8 +197,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
EmitSetNzcv(context, value);
|
EmitSetNzcv(context, value);
|
||||||
|
|
||||||
Operand q = context.ShiftRightUI(value, Const((int)PState.QFlag));
|
Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
|
||||||
q = context.BitwiseAnd(q, Const(1));
|
|
||||||
|
|
||||||
SetFlag(context, PState.QFlag, q);
|
SetFlag(context, PState.QFlag, q);
|
||||||
}
|
}
|
||||||
@@ -284,17 +280,10 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
||||||
{
|
{
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
|
||||||
v = context.BitwiseAnd(v, Const(1));
|
Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
|
||||||
|
Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
|
||||||
c = context.BitwiseAnd(c, Const(1));
|
|
||||||
|
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
|
||||||
z = context.BitwiseAnd(z, Const(1));
|
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
|
||||||
n = context.BitwiseAnd(n, Const(1));
|
|
||||||
|
|
||||||
SetFlag(context, PState.VFlag, v);
|
SetFlag(context, PState.VFlag, v);
|
||||||
SetFlag(context, PState.CFlag, c);
|
SetFlag(context, PState.CFlag, c);
|
||||||
@@ -306,42 +295,32 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||||
|
|
||||||
Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag));
|
Operand fpscr = Const(0);
|
||||||
Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag));
|
|
||||||
Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag));
|
|
||||||
Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag));
|
|
||||||
|
|
||||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));
|
SetIntA32(context, op.Rt, fpscr);
|
||||||
|
|
||||||
SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSetFpscr(ArmEmitterContext context)
|
private static void EmitSetFpscr(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||||
|
|
||||||
Operand t = GetIntA32(context, op.Rt);
|
Operand fpscr = GetIntA32(context, op.Rt);
|
||||||
|
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)FPState.VFlag));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
v = context.BitwiseAnd(v, Const(1));
|
{
|
||||||
|
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)FPState.CFlag));
|
{
|
||||||
c = context.BitwiseAnd(c, Const(1));
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)FPState.ZFlag));
|
}
|
||||||
z = context.BitwiseAnd(z, Const(1));
|
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)FPState.NFlag));
|
|
||||||
n = context.BitwiseAnd(n, Const(1));
|
|
||||||
|
|
||||||
SetFpFlag(context, FPState.VFlag, v);
|
|
||||||
SetFpFlag(context, FPState.CFlag, c);
|
|
||||||
SetFpFlag(context, FPState.ZFlag, z);
|
|
||||||
SetFpFlag(context, FPState.NFlag, n);
|
|
||||||
|
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)), t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -72,29 +72,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return (ulong)GetContext().DczidEl0;
|
return (ulong)GetContext().DczidEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong GetFpcr()
|
|
||||||
{
|
|
||||||
return (ulong)GetContext().Fpcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool GetFpcrFz()
|
|
||||||
{
|
|
||||||
return (GetContext().Fpcr & FPCR.Fz) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetFpsr()
|
|
||||||
{
|
|
||||||
return (ulong)GetContext().Fpsr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint GetFpscr()
|
|
||||||
{
|
|
||||||
ExecutionContext context = GetContext();
|
|
||||||
|
|
||||||
return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
|
|
||||||
(uint)(context.Fpcr & FPCR.A32Mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetTpidrEl0()
|
public static ulong GetTpidrEl0()
|
||||||
{
|
{
|
||||||
return (ulong)GetContext().TpidrEl0;
|
return (ulong)GetContext().TpidrEl0;
|
||||||
@@ -130,29 +107,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return GetContext().CntvctEl0;
|
return GetContext().CntvctEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetFpcr(ulong value)
|
|
||||||
{
|
|
||||||
GetContext().Fpcr = (FPCR)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpsr(ulong value)
|
|
||||||
{
|
|
||||||
GetContext().Fpsr = (FPSR)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpsrQc()
|
|
||||||
{
|
|
||||||
GetContext().Fpsr |= FPSR.Qc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpscr(uint fpscr)
|
|
||||||
{
|
|
||||||
ExecutionContext context = GetContext();
|
|
||||||
|
|
||||||
context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
|
|
||||||
context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetTpidrEl0(ulong value)
|
public static void SetTpidrEl0(ulong value)
|
||||||
{
|
{
|
||||||
GetContext().TpidrEl0 = (long)value;
|
GetContext().TpidrEl0 = (long)value;
|
||||||
|
@@ -91,76 +91,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Rounding"
|
|
||||||
public static double Round(double value)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
|
||||||
|
|
||||||
if (roundMode == FPRoundingMode.ToNearest)
|
|
||||||
{
|
|
||||||
return Math.Round(value); // even
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
|
||||||
{
|
|
||||||
return Math.Ceiling(value);
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
|
||||||
{
|
|
||||||
return Math.Floor(value);
|
|
||||||
}
|
|
||||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
|
||||||
{
|
|
||||||
return Math.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float RoundF(float value)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
|
||||||
|
|
||||||
if (roundMode == FPRoundingMode.ToNearest)
|
|
||||||
{
|
|
||||||
return MathF.Round(value); // even
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
|
||||||
{
|
|
||||||
return MathF.Ceiling(value);
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
|
||||||
{
|
|
||||||
return MathF.Floor(value);
|
|
||||||
}
|
|
||||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
|
||||||
{
|
|
||||||
return MathF.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int FloatToInt32(float value)
|
|
||||||
{
|
|
||||||
return SatF32ToS32(RoundF(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int DoubleToInt32(double value)
|
|
||||||
{
|
|
||||||
return SatF64ToS32(Round(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint FloatToUInt32(float value)
|
|
||||||
{
|
|
||||||
return SatF32ToU32(RoundF(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint DoubleToUInt32(double value)
|
|
||||||
{
|
|
||||||
return SatF64ToU32(Round(value));
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "Saturation"
|
#region "Saturation"
|
||||||
public static int SatF32ToS32(float value)
|
public static int SatF32ToS32(float value)
|
||||||
{
|
{
|
||||||
|
@@ -12,8 +12,8 @@ namespace ARMeilleure.Instructions
|
|||||||
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static readonly byte[] RecipEstimateTable;
|
public static readonly byte[] RecipEstimateTable;
|
||||||
internal static readonly byte[] RecipSqrtEstimateTable;
|
public static readonly byte[] RecipSqrtEstimateTable;
|
||||||
|
|
||||||
private static byte[] BuildRecipEstimateTable()
|
private static byte[] BuildRecipEstimateTable()
|
||||||
{
|
{
|
||||||
@@ -94,6 +94,13 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Fpsr |= (FPSR)(1 << (int)exc);
|
context.Fpsr |= (FPSR)(1 << (int)exc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
||||||
|
{
|
||||||
|
const int RModeShift = 22;
|
||||||
|
|
||||||
|
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SoftFloat16
|
static class SoftFloat16
|
||||||
|
@@ -36,10 +36,25 @@ namespace ARMeilleure.State
|
|||||||
set => _nativeContext.SetPstate(value);
|
set => _nativeContext.SetPstate(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FPCR Fpcr { get; set; }
|
public FPSR Fpsr
|
||||||
public FPSR Fpsr { get; set; }
|
{
|
||||||
|
get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FPCR Fpcr
|
||||||
|
{
|
||||||
|
get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
|
||||||
|
}
|
||||||
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
||||||
|
|
||||||
|
public FPSCR Fpscr
|
||||||
|
{
|
||||||
|
get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsAarch32 { get; set; }
|
public bool IsAarch32 { get; set; }
|
||||||
|
|
||||||
internal ExecutionMode ExecutionMode
|
internal ExecutionMode ExecutionMode
|
||||||
|
@@ -5,21 +5,18 @@ namespace ARMeilleure.State
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum FPCR : uint
|
public enum FPCR : uint
|
||||||
{
|
{
|
||||||
|
Ioe = 1u << 8,
|
||||||
|
Dze = 1u << 9,
|
||||||
|
Ofe = 1u << 10,
|
||||||
Ufe = 1u << 11,
|
Ufe = 1u << 11,
|
||||||
|
Ixe = 1u << 12,
|
||||||
|
Ide = 1u << 15,
|
||||||
|
RMode0 = 1u << 22,
|
||||||
|
RMode1 = 1u << 23,
|
||||||
Fz = 1u << 24,
|
Fz = 1u << 24,
|
||||||
Dn = 1u << 25,
|
Dn = 1u << 25,
|
||||||
Ahp = 1u << 26,
|
Ahp = 1u << 26,
|
||||||
|
|
||||||
A32Mask = 0x07FF9F00u
|
Mask = Ahp | Dn | Fz | RMode1 | RMode0 | Ide | Ixe | Ufe | Ofe | Dze | Ioe // 0x07C09F00u
|
||||||
}
|
|
||||||
|
|
||||||
public static class FPCRExtensions
|
|
||||||
{
|
|
||||||
private const int RModeShift = 22;
|
|
||||||
|
|
||||||
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
|
||||||
{
|
|
||||||
return (FPRoundingMode)(((int)fpcr >> RModeShift) & 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
ARMeilleure/State/FPSCR.cs
Normal file
15
ARMeilleure/State/FPSCR.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ARMeilleure.State
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum FPSCR : uint
|
||||||
|
{
|
||||||
|
V = 1u << 28,
|
||||||
|
C = 1u << 29,
|
||||||
|
Z = 1u << 30,
|
||||||
|
N = 1u << 31,
|
||||||
|
|
||||||
|
Mask = N | Z | C | V | FPSR.Mask | FPCR.Mask // 0xFFC09F9Fu
|
||||||
|
}
|
||||||
|
}
|
@@ -5,11 +5,14 @@ namespace ARMeilleure.State
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum FPSR : uint
|
public enum FPSR : uint
|
||||||
{
|
{
|
||||||
|
Ioc = 1u << 0,
|
||||||
|
Dzc = 1u << 1,
|
||||||
|
Ofc = 1u << 2,
|
||||||
Ufc = 1u << 3,
|
Ufc = 1u << 3,
|
||||||
Qc = 1u << 27,
|
Ixc = 1u << 4,
|
||||||
|
Idc = 1u << 7,
|
||||||
|
Qc = 1u << 27,
|
||||||
|
|
||||||
Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
|
Mask = Qc | Idc | Ixc | Ufc | Ofc | Dzc | Ioc // 0x0800009Fu
|
||||||
|
|
||||||
A32Mask = 0xF800009Fu
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,30 @@
|
|||||||
{
|
{
|
||||||
public enum FPState
|
public enum FPState
|
||||||
{
|
{
|
||||||
|
// FPSR Flags.
|
||||||
|
IocFlag = 0,
|
||||||
|
DzcFlag = 1,
|
||||||
|
OfcFlag = 2,
|
||||||
|
UfcFlag = 3,
|
||||||
|
IxcFlag = 4,
|
||||||
|
IdcFlag = 7,
|
||||||
|
QcFlag = 27,
|
||||||
VFlag = 28,
|
VFlag = 28,
|
||||||
CFlag = 29,
|
CFlag = 29,
|
||||||
ZFlag = 30,
|
ZFlag = 30,
|
||||||
NFlag = 31
|
NFlag = 31,
|
||||||
|
|
||||||
|
// FPCR Flags.
|
||||||
|
IoeFlag = 8,
|
||||||
|
DzeFlag = 9,
|
||||||
|
OfeFlag = 10,
|
||||||
|
UfeFlag = 11,
|
||||||
|
IxeFlag = 12,
|
||||||
|
IdeFlag = 15,
|
||||||
|
RMode0Flag = 22,
|
||||||
|
RMode1Flag = 23,
|
||||||
|
FzFlag = 24,
|
||||||
|
DnFlag = 25,
|
||||||
|
AhpFlag = 26
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -140,6 +140,34 @@ namespace ARMeilleure.State
|
|||||||
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
|
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe uint GetFPState(uint mask = uint.MaxValue)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
uint bit = 1u << flag;
|
||||||
|
|
||||||
|
if ((mask & bit) == bit)
|
||||||
|
{
|
||||||
|
value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
|
||||||
|
{
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
uint bit = 1u << flag;
|
||||||
|
|
||||||
|
if ((mask & bit) == bit)
|
||||||
|
{
|
||||||
|
GetStorage().FpFlags[flag] = (value & bit) == bit ? 1u : 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int GetCounter() => GetStorage().Counter;
|
public int GetCounter() => GetStorage().Counter;
|
||||||
public void SetCounter(int value) => GetStorage().Counter = value;
|
public void SetCounter(int value) => GetStorage().Counter = value;
|
||||||
|
|
||||||
|
@@ -109,10 +109,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
||||||
@@ -124,10 +120,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
||||||
@@ -151,12 +143,8 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
||||||
@@ -165,8 +153,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
||||||
|
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 3700; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 3703; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
@@ -162,7 +162,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
_context.SetPstateFlag(PState.ZFlag, zero);
|
_context.SetPstateFlag(PState.ZFlag, zero);
|
||||||
_context.SetPstateFlag(PState.NFlag, negative);
|
_context.SetPstateFlag(PState.NFlag, negative);
|
||||||
|
|
||||||
SetFpscr((uint)fpscr);
|
_context.Fpscr = (FPSCR)fpscr;
|
||||||
|
|
||||||
_context.SetPstateFlag(PState.TFlag, thumb);
|
_context.SetPstateFlag(PState.TFlag, thumb);
|
||||||
|
|
||||||
@@ -467,7 +467,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
Assert.That(_context.GetPstateFlag(PState.NFlag), Is.EqualTo(_unicornEmu.NegativeFlag), "NFlag");
|
Assert.That(_context.GetPstateFlag(PState.NFlag), Is.EqualTo(_unicornEmu.NegativeFlag), "NFlag");
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.That((int)GetFpscr() & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpscr & (int)fpsrMask), "Fpscr");
|
Assert.That((int)_context.Fpscr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpscr & (int)fpsrMask), "Fpscr");
|
||||||
|
|
||||||
if (_usingMemory)
|
if (_usingMemory)
|
||||||
{
|
{
|
||||||
@@ -650,28 +650,5 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
|
|
||||||
return rnd & 0x800FFFFFFFFFFFFFul;
|
return rnd & 0x800FFFFFFFFFFFFFul;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint GetFpscr()
|
|
||||||
{
|
|
||||||
uint fpscr = (uint)(_context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) | (uint)(_context.Fpcr & FPCR.A32Mask);
|
|
||||||
|
|
||||||
fpscr |= _context.GetFPstateFlag(FPState.NFlag) ? (1u << (int)FPState.NFlag) : 0;
|
|
||||||
fpscr |= _context.GetFPstateFlag(FPState.ZFlag) ? (1u << (int)FPState.ZFlag) : 0;
|
|
||||||
fpscr |= _context.GetFPstateFlag(FPState.CFlag) ? (1u << (int)FPState.CFlag) : 0;
|
|
||||||
fpscr |= _context.GetFPstateFlag(FPState.VFlag) ? (1u << (int)FPState.VFlag) : 0;
|
|
||||||
|
|
||||||
return fpscr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetFpscr(uint fpscr)
|
|
||||||
{
|
|
||||||
_context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
|
|
||||||
_context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
|
|
||||||
|
|
||||||
_context.SetFPstateFlag(FPState.NFlag, (fpscr & (1u << (int)FPState.NFlag)) != 0);
|
|
||||||
_context.SetFPstateFlag(FPState.ZFlag, (fpscr & (1u << (int)FPState.ZFlag)) != 0);
|
|
||||||
_context.SetFPstateFlag(FPState.CFlag, (fpscr & (1u << (int)FPState.CFlag)) != 0);
|
|
||||||
_context.SetFPstateFlag(FPState.VFlag, (fpscr & (1u << (int)FPState.VFlag)) != 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user