Stop using GetFunctionPointer as that can't be called from native code, misc. fixes and tweaks

This commit is contained in:
gdkchan 2019-07-17 19:29:19 -03:00
commit 686f7f4ff2
48 changed files with 1952 additions and 2888 deletions

View file

@ -67,12 +67,24 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
fixedIntervals[0] = new List<LiveInterval>(); fixedIntervals[0] = new List<LiveInterval>();
fixedIntervals[1] = new List<LiveInterval>(); fixedIntervals[1] = new List<LiveInterval>();
int intUsedRegisters = 0;
int vecUsedRegisters = 0;
for (int index = 0; index < RegistersCount * 2; index++) for (int index = 0; index < RegistersCount * 2; index++)
{ {
LiveInterval interval = _intervals[index]; LiveInterval interval = _intervals[index];
if (!interval.IsEmpty) if (!interval.IsEmpty)
{ {
if (interval.Register.Type == RegisterType.Integer)
{
intUsedRegisters |= 1 << interval.Register.Index;
}
else /* if (interval.Register.Type == RegisterType.Vector) */
{
vecUsedRegisters |= 1 << interval.Register.Index;
}
InsertSorted(fixedIntervals[index & 1], interval); InsertSorted(fixedIntervals[index & 1], interval);
} }
} }
@ -84,9 +96,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int intFreeRegisters = regMasks.IntAvailableRegisters; int intFreeRegisters = regMasks.IntAvailableRegisters;
int vecFreeRegisters = regMasks.VecAvailableRegisters; int vecFreeRegisters = regMasks.VecAvailableRegisters;
int intUsedRegisters = 0;
int vecUsedRegisters = 0;
intFreeRegisters = ReserveSpillTemps(ref _intSpillTemps, intFreeRegisters); intFreeRegisters = ReserveSpillTemps(ref _intSpillTemps, intFreeRegisters);
vecFreeRegisters = ReserveSpillTemps(ref _vecSpillTemps, vecFreeRegisters); vecFreeRegisters = ReserveSpillTemps(ref _vecSpillTemps, vecFreeRegisters);
@ -413,29 +422,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operation operation = node.Value as Operation; Operation operation = node.Value as Operation;
Operand dest = operation.Dest; // Note: For fixed intervals, we must process sources first, in
// order to extend the live range of the fixed interval to the last
if (dest != null) // use, in case the register is both used and assigned on the same
{ // instruction.
if (dest.Kind == OperandKind.LocalVariable)
{
LiveInterval interval = GetOrAddInterval(dest);
if (interval.IsEmpty)
{
interval.SetStart(operationPos + 1);
}
interval.AddUsePosition(operationPos);
}
else if (dest.Kind == OperandKind.Register)
{
int iIndex = GetRegisterId(dest.GetRegister());
_intervals[iIndex].AddRange(operationPos + 1, operationPos + InstructionGap);
}
}
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
{ {
Operand source = operation.GetSource(srcIndex); Operand source = operation.GetSource(srcIndex);
@ -466,6 +456,29 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
} }
Operand dest = operation.Dest;
if (dest != null)
{
if (dest.Kind == OperandKind.LocalVariable)
{
LiveInterval interval = GetOrAddInterval(dest);
if (interval.IsEmpty)
{
interval.SetStart(operationPos + 1);
}
interval.AddUsePosition(operationPos);
}
else if (dest.Kind == OperandKind.Register)
{
int iIndex = GetRegisterId(dest.GetRegister());
_intervals[iIndex].AddRange(operationPos + 1, operationPos + InstructionGap);
}
}
if (operation.Inst == Instruction.Call) if (operation.Inst == Instruction.Call)
{ {
AddIntervalCallerSavedReg(masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer); AddIntervalCallerSavedReg(masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);

View file

@ -91,6 +91,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
context.Active.Set(index); context.Active.Set(index);
if (current.Register.Type == RegisterType.Integer)
{
context.IntUsedRegisters |= 1 << current.Register.Index;
}
else /* if (interval.Register.Type == RegisterType.Vector) */
{
context.VecUsedRegisters |= 1 << current.Register.Index;
}
continue; continue;
} }

View file

@ -84,7 +84,6 @@ namespace ARMeilleure.CodeGen.X86
Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW)); Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2)); Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3)); Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Cmpxchg8b, new InstInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstFlags.NoRexW));
Add(X86Instruction.Cmpxchg16b, new InstInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstFlags.RexW)); Add(X86Instruction.Cmpxchg16b, new InstInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstFlags.RexW));
Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66)); Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW)); Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW));
@ -263,16 +262,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.Add); WriteInstruction(dest, source, X86Instruction.Add);
} }
public void Addpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Addpd, source1);
}
public void Addps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Addps, source1);
}
public void Addsd(Operand dest, Operand source, Operand source1) public void Addsd(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Addsd, source1); WriteInstruction(dest, source, X86Instruction.Addsd, source1);
@ -288,16 +277,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.And); WriteInstruction(dest, source, X86Instruction.And);
} }
public void Andnpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Andnpd, source1);
}
public void Andnps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Andnps, source1);
}
public void Bsr(Operand dest, Operand source) public void Bsr(Operand dest, Operand source)
{ {
WriteInstruction(dest, source, X86Instruction.Bsr); WriteInstruction(dest, source, X86Instruction.Bsr);
@ -336,34 +315,6 @@ namespace ARMeilleure.CodeGen.X86
WriteByte(0x99); WriteByte(0x99);
} }
public void Cmppd(Operand dest, Operand source, Operand source1, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Cmppd, source1);
WriteByte(imm);
}
public void Cmpps(Operand dest, Operand source, Operand source1, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Cmpps, source1);
WriteByte(imm);
}
public void Cmpsd(Operand dest, Operand source, Operand source1, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Cmpsd, source1);
WriteByte(imm);
}
public void Cmpss(Operand dest, Operand source, Operand source1, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Cmpss, source1);
WriteByte(imm);
}
public void Cmpxchg16b(X86MemoryOperand memOp) public void Cmpxchg16b(X86MemoryOperand memOp)
{ {
WriteByte(LockPrefix); WriteByte(LockPrefix);
@ -371,13 +322,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(memOp, null, X86Instruction.Cmpxchg16b); WriteInstruction(memOp, null, X86Instruction.Cmpxchg16b);
} }
public void Cmpxchg8b(X86MemoryOperand memOp)
{
WriteByte(LockPrefix);
WriteInstruction(memOp, null, X86Instruction.Cmpxchg8b);
}
public void Comisd(Operand source1, Operand source2) public void Comisd(Operand source1, Operand source2)
{ {
WriteInstruction(source1, source2, X86Instruction.Comisd); WriteInstruction(source1, source2, X86Instruction.Comisd);
@ -388,41 +332,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(source1, source2, X86Instruction.Comiss); WriteInstruction(source1, source2, X86Instruction.Comiss);
} }
public void Cvtdq2pd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtdq2pd);
}
public void Cvtdq2ps(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtdq2ps);
}
public void Cvtpd2dq(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtpd2dq);
}
public void Cvtpd2ps(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtpd2ps);
}
public void Cvtps2dq(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtps2dq);
}
public void Cvtps2pd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtps2pd);
}
public void Cvtsd2si(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Cvtsd2si);
}
public void Cvtsd2ss(Operand dest, Operand source, Operand source1) public void Cvtsd2ss(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Cvtsd2ss, source1); WriteInstruction(dest, source, X86Instruction.Cvtsd2ss, source1);
@ -448,16 +357,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(null, source, X86Instruction.Div); WriteInstruction(null, source, X86Instruction.Div);
} }
public void Divpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Divpd, source1);
}
public void Divps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Divps, source1);
}
public void Divsd(Operand dest, Operand source, Operand source1) public void Divsd(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Divsd, source1); WriteInstruction(dest, source, X86Instruction.Divsd, source1);
@ -468,16 +367,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.Divss, source1); WriteInstruction(dest, source, X86Instruction.Divss, source1);
} }
public void Haddpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Haddpd, source1);
}
public void Haddps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Haddps, source1);
}
public void Idiv(Operand source) public void Idiv(Operand source)
{ {
WriteInstruction(null, source, X86Instruction.Idiv); WriteInstruction(null, source, X86Instruction.Idiv);
@ -578,46 +467,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.Lea); WriteInstruction(dest, source, X86Instruction.Lea);
} }
public void Maxpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Maxpd, source1);
}
public void Maxps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Maxps, source1);
}
public void Maxsd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Maxsd, source1);
}
public void Maxss(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Maxss, source1);
}
public void Minpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Minpd, source1);
}
public void Minps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Minps, source1);
}
public void Minsd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Minsd, source1);
}
public void Minss(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Minss, source1);
}
public void Mov(Operand dest, Operand source) public void Mov(Operand dest, Operand source)
{ {
WriteInstruction(dest, source, X86Instruction.Mov); WriteInstruction(dest, source, X86Instruction.Mov);
@ -707,16 +556,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(null, source, X86Instruction.Mul128); WriteInstruction(null, source, X86Instruction.Mul128);
} }
public void Mulpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Mulpd, source1);
}
public void Mulps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Mulps, source1);
}
public void Mulsd(Operand dest, Operand source, Operand source1) public void Mulsd(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Mulsd, source1); WriteInstruction(dest, source, X86Instruction.Mulsd, source1);
@ -742,94 +581,11 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.Or); WriteInstruction(dest, source, X86Instruction.Or);
} }
public void Paddb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Paddb, source1);
}
public void Paddd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Paddd, source1);
}
public void Paddq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Paddq, source1);
}
public void Paddw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Paddw, source1);
}
public void Pand(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pand, source1);
}
public void Pandn(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pandn, source1);
}
public void Pavgb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pavgb, source1);
}
public void Pavgw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pavgw, source1);
}
public void Pblendvb(Operand dest, Operand source1, Operand source2, Operand source3)
{
//TODO: Non-VEX version.
WriteInstruction(dest, source2, X86Instruction.Pblendvb, source1);
WriteByte((byte)(source3.AsByte() << 4));
}
public void Pcmpeqb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpeqb, source1);
}
public void Pcmpeqd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpeqd, source1);
}
public void Pcmpeqq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpeqq, source1);
}
public void Pcmpeqw(Operand dest, Operand source, Operand source1) public void Pcmpeqw(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Pcmpeqw, source1); WriteInstruction(dest, source, X86Instruction.Pcmpeqw, source1);
} }
public void Pcmpgtb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpgtb, source1);
}
public void Pcmpgtd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpgtd, source1);
}
public void Pcmpgtq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpgtq, source1);
}
public void Pcmpgtw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pcmpgtw, source1);
}
public void Pextrb(Operand dest, Operand source, byte imm) public void Pextrb(Operand dest, Operand source, byte imm)
{ {
WriteInstruction(dest, source, X86Instruction.Pextrb); WriteInstruction(dest, source, X86Instruction.Pextrb);
@ -872,106 +628,6 @@ namespace ARMeilleure.CodeGen.X86
WriteByte(imm); WriteByte(imm);
} }
public void Pmaxsb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxsb, source1);
}
public void Pmaxsd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxsd, source1);
}
public void Pmaxsw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxsw, source1);
}
public void Pmaxub(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxub, source1);
}
public void Pmaxud(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxud, source1);
}
public void Pmaxuw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmaxuw, source1);
}
public void Pminsb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminsb, source1);
}
public void Pminsd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminsd, source1);
}
public void Pminsw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminsw, source1);
}
public void Pminub(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminub, source1);
}
public void Pminud(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminud, source1);
}
public void Pminuw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pminuw, source1);
}
public void Pmovsxbw(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovsxbw);
}
public void Pmovsxdq(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovsxdq);
}
public void Pmovsxwd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovsxwd);
}
public void Pmovzxbw(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovzxbw);
}
public void Pmovzxdq(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovzxdq);
}
public void Pmovzxwd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Pmovzxwd);
}
public void Pmulld(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmulld, source1);
}
public void Pmullw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pmullw, source1);
}
public void Pop(Operand dest) public void Pop(Operand dest)
{ {
if (dest.Kind == OperandKind.Register) if (dest.Kind == OperandKind.Register)
@ -989,16 +645,6 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, source, X86Instruction.Popcnt); WriteInstruction(dest, source, X86Instruction.Popcnt);
} }
public void Por(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Por, source1);
}
public void Pshufb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pshufb, source1);
}
public void Pshufd(Operand dest, Operand source, byte imm) public void Pshufd(Operand dest, Operand source, byte imm)
{ {
WriteInstruction(dest, source, X86Instruction.Pshufd); WriteInstruction(dest, source, X86Instruction.Pshufd);
@ -1006,116 +652,6 @@ namespace ARMeilleure.CodeGen.X86
WriteByte(imm); WriteByte(imm);
} }
public void Pslld(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Pslld, dest);
}
public void Pslldq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Pslldq, dest);
}
public void Psllq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psllq, dest);
}
public void Psllw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psllw, dest);
}
public void Psrad(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psrad, dest);
}
public void Psraw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psraw, dest);
}
public void Psrld(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psrld, dest);
}
public void Psrlq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psrlq, dest);
}
public void Psrldq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psrldq, dest);
}
public void Psrlw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(source1, source, X86Instruction.Psrlw, dest);
}
public void Psubb(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Psubb, source1);
}
public void Psubd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Psubd, source1);
}
public void Psubq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Psubq, source1);
}
public void Psubw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Psubw, source1);
}
public void Punpckhbw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpckhbw, source1);
}
public void Punpckhdq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpckhdq, source1);
}
public void Punpckhqdq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpckhqdq, source1);
}
public void Punpckhwd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpckhwd, source1);
}
public void Punpcklbw(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpcklbw, source1);
}
public void Punpckldq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpckldq, source1);
}
public void Punpcklqdq(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpcklqdq, source1);
}
public void Punpcklwd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Punpcklwd, source1);
}
public void Push(Operand source) public void Push(Operand source)
{ {
if (source.Kind == OperandKind.Register) if (source.Kind == OperandKind.Register)
@ -1128,21 +664,6 @@ namespace ARMeilleure.CodeGen.X86
} }
} }
public void Pxor(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Pxor, source1);
}
public void Rcpps(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Rcpps);
}
public void Rcpss(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Rcpss);
}
public void Return() public void Return()
{ {
WriteByte(0xc3); WriteByte(0xc3);
@ -1153,44 +674,6 @@ namespace ARMeilleure.CodeGen.X86
WriteShiftInst(dest, source, X86Instruction.Ror); WriteShiftInst(dest, source, X86Instruction.Ror);
} }
public void Roundpd(Operand dest, Operand source, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Roundpd);
WriteByte(imm);
}
public void Roundps(Operand dest, Operand source, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Roundps);
WriteByte(imm);
}
public void Roundsd(Operand dest, Operand source, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Roundsd);
WriteByte(imm);
}
public void Roundss(Operand dest, Operand source, byte imm)
{
WriteInstruction(dest, source, X86Instruction.Roundss);
WriteByte(imm);
}
public void Rsqrtps(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Rsqrtps);
}
public void Rsqrtss(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Rsqrtss);
}
public void Sar(Operand dest, Operand source) public void Sar(Operand dest, Operand source)
{ {
WriteShiftInst(dest, source, X86Instruction.Sar); WriteShiftInst(dest, source, X86Instruction.Sar);
@ -1206,20 +689,6 @@ namespace ARMeilleure.CodeGen.X86
WriteShiftInst(dest, source, X86Instruction.Shr); WriteShiftInst(dest, source, X86Instruction.Shr);
} }
public void Shufpd(Operand dest, Operand source, byte imm, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Shufpd, source1);
WriteByte(imm);
}
public void Shufps(Operand dest, Operand source, byte imm, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Shufps, source1);
WriteByte(imm);
}
public void Setcc(Operand dest, X86Condition condition) public void Setcc(Operand dest, X86Condition condition)
{ {
InstInfo info = _instTable[(int)X86Instruction.Setcc]; InstInfo info = _instTable[(int)X86Instruction.Setcc];
@ -1227,41 +696,11 @@ namespace ARMeilleure.CodeGen.X86
WriteOpCode(dest, null, info.Flags, info.OpRRM | (int)condition); WriteOpCode(dest, null, info.Flags, info.OpRRM | (int)condition);
} }
public void Sqrtpd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Sqrtpd);
}
public void Sqrtps(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Sqrtps);
}
public void Sqrtsd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Sqrtsd);
}
public void Sqrtss(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Sqrtss);
}
public void Sub(Operand dest, Operand source) public void Sub(Operand dest, Operand source)
{ {
WriteInstruction(dest, source, X86Instruction.Sub); WriteInstruction(dest, source, X86Instruction.Sub);
} }
public void Subpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Subpd, source1);
}
public void Subps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Subps, source1);
}
public void Subsd(Operand dest, Operand source, Operand source1) public void Subsd(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Subsd, source1); WriteInstruction(dest, source, X86Instruction.Subsd, source1);
@ -1277,41 +716,65 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(src1, src2, X86Instruction.Test); WriteInstruction(src1, src2, X86Instruction.Test);
} }
public void Unpckhpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Unpckhpd, source1);
}
public void Unpckhps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Unpckhps, source1);
}
public void Unpcklpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Unpcklpd, source1);
}
public void Unpcklps(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Unpcklps, source1);
}
public void Xor(Operand dest, Operand source) public void Xor(Operand dest, Operand source)
{ {
WriteInstruction(dest, source, X86Instruction.Xor); WriteInstruction(dest, source, X86Instruction.Xor);
} }
public void Xorpd(Operand dest, Operand source, Operand source1)
{
WriteInstruction(dest, source, X86Instruction.Xorpd, source1);
}
public void Xorps(Operand dest, Operand source, Operand source1) public void Xorps(Operand dest, Operand source, Operand source1)
{ {
WriteInstruction(dest, source, X86Instruction.Xorps, source1); WriteInstruction(dest, source, X86Instruction.Xorps, source1);
} }
public void WriteInstruction(X86Instruction inst, Operand dest, Operand source)
{
WriteInstruction(dest, source, inst);
}
public void WriteInstruction(X86Instruction inst, Operand dest, Operand src1, Operand src2)
{
if (src2.Kind == OperandKind.Constant)
{
WriteInstruction(src1, src2, inst, dest);
}
else
{
WriteInstruction(dest, src2, inst, src1);
}
}
public void WriteInstruction(X86Instruction inst, Operand dest, Operand source, byte imm)
{
WriteInstruction(dest, source, inst);
WriteByte(imm);
}
public void WriteInstruction(
X86Instruction inst,
Operand dest,
Operand src1,
Operand src2,
Operand src3)
{
//TODO: Non-VEX version.
WriteInstruction(dest, src2, inst, src1);
WriteByte((byte)(src3.AsByte() << 4));
}
public void WriteInstruction(
X86Instruction inst,
Operand dest,
Operand src1,
Operand src2,
byte imm)
{
WriteInstruction(dest, src2, inst, src1);
WriteByte(imm);
}
private void WriteShiftInst(Operand dest, Operand source, X86Instruction inst) private void WriteShiftInst(Operand dest, Operand source, X86Instruction inst)
{ {
if (source.Kind == OperandKind.Register) if (source.Kind == OperandKind.Register)

File diff suppressed because it is too large Load diff

View file

@ -101,8 +101,6 @@ namespace ARMeilleure.CodeGen.X86
if (src1.Kind == OperandKind.Constant) if (src1.Kind == OperandKind.Constant)
{ {
bool isVecCopy = inst == Instruction.Copy && !dest.Type.IsInteger();
if (!src1.Type.IsInteger()) if (!src1.Type.IsInteger())
{ {
//Handle non-integer types (FP32, FP64 and V128). //Handle non-integer types (FP32, FP64 and V128).
@ -114,7 +112,7 @@ namespace ARMeilleure.CodeGen.X86
operation.SetSource(0, src1); operation.SetSource(0, src1);
} }
else if (!HasConstSrc1(inst) || isVecCopy) else if (!HasConstSrc1(inst))
{ {
//Handle integer types. //Handle integer types.
//Most ALU instructions accepts a 32-bits immediate on the second operand. //Most ALU instructions accepts a 32-bits immediate on the second operand.
@ -331,7 +329,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rdx = Gpr(X86Register.Rdx, OperandType.I64); Operand rdx = Gpr(X86Register.Rdx, OperandType.I64);
node.List.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1))); node.List.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
node.List.AddAfter(node, new Operation(Instruction.Copy, dest, rax)); node.List.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, rax));
operation.SetSource(1, Undef()); operation.SetSource(1, Undef());
operation.SetSource(2, Undef()); operation.SetSource(2, Undef());
@ -661,7 +659,9 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand temp = Local(source.Type); Operand temp = Local(source.Type);
Operation copyOp = new Operation(Instruction.Copy, temp, AddCopy(node, GetIntConst(source))); Operand intConst = AddCopy(node, GetIntConst(source));
Operation copyOp = new Operation(Instruction.VectorCreateScalar, temp, intConst);
node.List.AddBefore(node, copyOp); node.List.AddBefore(node, copyOp);

View file

@ -20,7 +20,6 @@ namespace ARMeilleure.CodeGen.X86
Cmpsd, Cmpsd,
Cmpss, Cmpss,
Cmpxchg16b, Cmpxchg16b,
Cmpxchg8b,
Comisd, Comisd,
Comiss, Comiss,
Cvtdq2pd, Cvtdq2pd,

View file

@ -314,23 +314,18 @@ namespace ARMeilleure.Decoders
} }
} }
OpCode decodedOpCode = new OpCode(inst, address, opCode);
if (type != null) if (type != null)
{ {
decodedOpCode = MakeOpCode(inst, type, address, opCode); return MakeOpCode(inst, type, address, opCode);
}
else
{
return new OpCode(inst, address, opCode);
} }
return decodedOpCode;
} }
private static OpCode MakeOpCode(InstDescriptor inst, Type type, ulong address, int opCode) private static OpCode MakeOpCode(InstDescriptor inst, Type type, ulong address, int opCode)
{ {
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
MakeOp createInstance = _opActivators.GetOrAdd(type, CacheOpActivator); MakeOp createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
return (OpCode)createInstance(inst, address, opCode); return (OpCode)createInstance(inst, address, opCode);

View file

@ -2,5 +2,5 @@ using ARMeilleure.Translation;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
delegate void InstEmitter(EmitterContext context); delegate void InstEmitter(ArmEmitterContext context);
} }

View file

@ -15,11 +15,9 @@ namespace ARMeilleure.Diagnostics
_accumulatedTime = new long[(int)PassName.Count]; _accumulatedTime = new long[(int)PassName.Count];
} }
public static bool DoLog;
public static void StartPass(PassName name) public static void StartPass(PassName name)
{ {
#if M_DEBUG #if DEBUG
WriteOutput(name + " pass started..."); WriteOutput(name + " pass started...");
_startTime = Stopwatch.GetTimestamp(); _startTime = Stopwatch.GetTimestamp();
@ -28,7 +26,7 @@ namespace ARMeilleure.Diagnostics
public static void EndPass(PassName name, ControlFlowGraph cfg) public static void EndPass(PassName name, ControlFlowGraph cfg)
{ {
#if M_DEBUG #if DEBUG
EndPass(name); EndPass(name);
WriteOutput("IR after " + name + " pass:"); WriteOutput("IR after " + name + " pass:");
@ -39,7 +37,7 @@ namespace ARMeilleure.Diagnostics
public static void EndPass(PassName name) public static void EndPass(PassName name)
{ {
#if M_DEBUG #if DEBUG
long elapsedTime = Stopwatch.GetTimestamp() - _startTime; long elapsedTime = Stopwatch.GetTimestamp() - _startTime;
_accumulatedTime[(int)name] += elapsedTime; _accumulatedTime[(int)name] += elapsedTime;

View file

@ -0,0 +1,78 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions
{
delegate double _F64_F64(double a1);
delegate double _F64_F64_F64(double a1, double a2);
delegate double _F64_F64_F64_F64(double a1, double a2, double a3);
delegate double _F64_F64_MidpointRounding(double a1, MidpointRounding a2);
delegate float _F32_F32(float a1);
delegate float _F32_F32_F32(float a1, float a2);
delegate float _F32_F32_F32_F32(float a1, float a2, float a3);
delegate float _F32_F32_MidpointRounding(float a1, MidpointRounding a2);
delegate float _F32_U16(ushort a1);
delegate int _S32_F32(float a1);
delegate int _S32_F32_F32_Bool(float a1, float a2, bool a3);
delegate int _S32_F64(double a1);
delegate int _S32_F64_F64_Bool(double a1, double a2, bool a3);
delegate int _S32_U64_U16(ulong a1, ushort a2);
delegate int _S32_U64_U32(ulong a1, uint a2);
delegate int _S32_U64_U64(ulong a1, ulong a2);
delegate int _S32_U64_U8(ulong a1, byte a2);
delegate int _S32_U64_V128(ulong a1, V128 a2);
delegate long _S64_F32(float a1);
delegate long _S64_F64(double a1);
delegate long _S64_S64(long a1);
delegate long _S64_S64_S32(long a1, int a2);
delegate long _S64_S64_S64(long a1, long a2);
delegate long _S64_S64_S64_Bool_S32(long a1, long a2, bool a3, int a4);
delegate long _S64_S64_S64_S32(long a1, long a2, int a3);
delegate long _S64_U64_S32(ulong a1, int a2);
delegate long _S64_U64_S64(ulong a1, long a2);
delegate ushort _U16_F32(float a1);
delegate ushort _U16_U64(ulong a1);
delegate uint _U32_F32(float a1);
delegate uint _U32_F64(double a1);
delegate uint _U32_U32(uint a1);
delegate uint _U32_U32_U16(uint a1, ushort a2);
delegate uint _U32_U32_U32(uint a1, uint a2);
delegate uint _U32_U32_U64(uint a1, ulong a2);
delegate uint _U32_U32_U8(uint a1, byte a2);
delegate uint _U32_U64(ulong a1);
delegate ulong _U64();
delegate ulong _U64_F32(float a1);
delegate ulong _U64_F64(double a1);
delegate ulong _U64_S64_S32(long a1, int a2);
delegate ulong _U64_S64_U64(long a1, ulong a2);
delegate ulong _U64_U64(ulong a1);
delegate ulong _U64_U64_S32(ulong a1, int a2);
delegate ulong _U64_U64_S64_S32(ulong a1, long a2, int a3);
delegate ulong _U64_U64_U64(ulong a1, ulong a2);
delegate ulong _U64_U64_U64_Bool_S32(ulong a1, ulong a2, bool a3, int a4);
delegate byte _U8_U64(ulong a1);
delegate V128 _V128_U64(ulong a1);
delegate V128 _V128_V128(V128 a1);
delegate V128 _V128_V128_U32_V128(V128 a1, uint a2, V128 a3);
delegate V128 _V128_V128_V128(V128 a1, V128 a2);
delegate V128 _V128_V128_V128_V128(V128 a1, V128 a2, V128 a3);
delegate V128 _V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4);
delegate V128 _V128_V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4, V128 a5);
delegate void _Void();
delegate void _Void_U64(ulong a1);
delegate void _Void_U64_S32(ulong a1, int a2);
delegate void _Void_U64_U16(ulong a1, ushort a2);
delegate void _Void_U64_U32(ulong a1, uint a2);
delegate void _Void_U64_U64(ulong a1, ulong a2);
delegate void _Void_U64_U8(ulong a1, byte a2);
delegate void _Void_U64_V128(ulong a1, V128 a2);
}

View file

@ -11,10 +11,10 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Adc(EmitterContext context) => EmitAdc(context, setFlags: false); public static void Adc(ArmEmitterContext context) => EmitAdc(context, setFlags: false);
public static void Adcs(EmitterContext context) => EmitAdc(context, setFlags: true); public static void Adcs(ArmEmitterContext context) => EmitAdc(context, setFlags: true);
private static void EmitAdc(EmitterContext context, bool setFlags) private static void EmitAdc(ArmEmitterContext context, bool setFlags)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -41,16 +41,18 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void Add(EmitterContext context) public static void Add(ArmEmitterContext context)
{ {
SetAluD(context, context.Add(GetAluN(context), GetAluM(context))); SetAluD(context, context.Add(GetAluN(context), GetAluM(context)));
} }
public static void Adds(EmitterContext context) public static void Adds(ArmEmitterContext context)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
context.MarkComparison(n, m);
Operand d = context.Add(n, m); Operand d = context.Add(n, m);
EmitNZFlagsCheck(context, d); EmitNZFlagsCheck(context, d);
@ -61,12 +63,12 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void And(EmitterContext context) public static void And(ArmEmitterContext context)
{ {
SetAluD(context, context.BitwiseAnd(GetAluN(context), GetAluM(context))); SetAluD(context, context.BitwiseAnd(GetAluN(context), GetAluM(context)));
} }
public static void Ands(EmitterContext context) public static void Ands(ArmEmitterContext context)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -79,15 +81,15 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void Asrv(EmitterContext context) public static void Asrv(ArmEmitterContext context)
{ {
SetAluDOrZR(context, context.ShiftRightSI(GetAluN(context), GetAluMShift(context))); SetAluDOrZR(context, context.ShiftRightSI(GetAluN(context), GetAluMShift(context)));
} }
public static void Bic(EmitterContext context) => EmitBic(context, setFlags: false); public static void Bic(ArmEmitterContext context) => EmitBic(context, setFlags: false);
public static void Bics(EmitterContext context) => EmitBic(context, setFlags: true); public static void Bics(ArmEmitterContext context) => EmitBic(context, setFlags: true);
private static void EmitBic(EmitterContext context, bool setFlags) private static void EmitBic(ArmEmitterContext context, bool setFlags)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -103,7 +105,7 @@ namespace ARMeilleure.Instructions
SetAluD(context, d, setFlags); SetAluD(context, d, setFlags);
} }
public static void Cls(EmitterContext context) public static void Cls(ArmEmitterContext context)
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
@ -124,7 +126,7 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, res); SetAluDOrZR(context, res);
} }
public static void Clz(EmitterContext context) public static void Clz(ArmEmitterContext context)
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
@ -135,7 +137,7 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void Eon(EmitterContext context) public static void Eon(ArmEmitterContext context)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -145,12 +147,12 @@ namespace ARMeilleure.Instructions
SetAluD(context, d); SetAluD(context, d);
} }
public static void Eor(EmitterContext context) public static void Eor(ArmEmitterContext context)
{ {
SetAluD(context, context.BitwiseExclusiveOr(GetAluN(context), GetAluM(context))); SetAluD(context, context.BitwiseExclusiveOr(GetAluN(context), GetAluM(context)));
} }
public static void Extr(EmitterContext context) public static void Extr(ArmEmitterContext context)
{ {
OpCodeAluRs op = (OpCodeAluRs)context.CurrOp; OpCodeAluRs op = (OpCodeAluRs)context.CurrOp;
@ -177,20 +179,20 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, res); SetAluDOrZR(context, res);
} }
public static void Lslv(EmitterContext context) public static void Lslv(ArmEmitterContext context)
{ {
SetAluDOrZR(context, context.ShiftLeft(GetAluN(context), GetAluMShift(context))); SetAluDOrZR(context, context.ShiftLeft(GetAluN(context), GetAluMShift(context)));
} }
public static void Lsrv(EmitterContext context) public static void Lsrv(ArmEmitterContext context)
{ {
SetAluDOrZR(context, context.ShiftRightUI(GetAluN(context), GetAluMShift(context))); SetAluDOrZR(context, context.ShiftRightUI(GetAluN(context), GetAluMShift(context)));
} }
public static void Sbc(EmitterContext context) => EmitSbc(context, setFlags: false); public static void Sbc(ArmEmitterContext context) => EmitSbc(context, setFlags: false);
public static void Sbcs(EmitterContext context) => EmitSbc(context, setFlags: true); public static void Sbcs(ArmEmitterContext context) => EmitSbc(context, setFlags: true);
private static void EmitSbc(EmitterContext context, bool setFlags) private static void EmitSbc(ArmEmitterContext context, bool setFlags)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -217,16 +219,18 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void Sub(EmitterContext context) public static void Sub(ArmEmitterContext context)
{ {
SetAluD(context, context.Subtract(GetAluN(context), GetAluM(context))); SetAluD(context, context.Subtract(GetAluN(context), GetAluM(context)));
} }
public static void Subs(EmitterContext context) public static void Subs(ArmEmitterContext context)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
context.MarkComparison(n, m);
Operand d = context.Subtract(n, m); Operand d = context.Subtract(n, m);
EmitNZFlagsCheck(context, d); EmitNZFlagsCheck(context, d);
@ -237,7 +241,7 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
public static void Orn(EmitterContext context) public static void Orn(ArmEmitterContext context)
{ {
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -247,20 +251,50 @@ namespace ARMeilleure.Instructions
SetAluD(context, d); SetAluD(context, d);
} }
public static void Orr(EmitterContext context) public static void Orr(ArmEmitterContext context)
{ {
SetAluD(context, context.BitwiseOr(GetAluN(context), GetAluM(context))); SetAluD(context, context.BitwiseOr(GetAluN(context), GetAluM(context)));
} }
public static void Rbit(EmitterContext context) => EmitCall32_64(context, public static void Rbit(ArmEmitterContext context)
nameof(SoftFallback.ReverseBits32), {
nameof(SoftFallback.ReverseBits64)); OpCodeAlu op = (OpCodeAlu)context.CurrOp;
public static void Rev16(EmitterContext context) => EmitCall32_64(context, Operand n = GetIntOrZR(context, op.Rn);
nameof(SoftFallback.ReverseBytes16_32), Operand d;
nameof(SoftFallback.ReverseBytes16_64));
public static void Rev32(EmitterContext context) if (op.RegisterSize == RegisterSize.Int32)
{
d = context.Call(new _U32_U32(SoftFallback.ReverseBits32), n);
}
else
{
d = context.Call(new _U64_U64(SoftFallback.ReverseBits64), n);
}
SetAluDOrZR(context, d);
}
public static void Rev16(ArmEmitterContext context)
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(context, op.Rn);
Operand d;
if (op.RegisterSize == RegisterSize.Int32)
{
d = context.Call(new _U32_U32(SoftFallback.ReverseBytes16_32), n);
}
else
{
d = context.Call(new _U64_U64(SoftFallback.ReverseBytes16_64), n);
}
SetAluDOrZR(context, d);
}
public static void Rev32(ArmEmitterContext context)
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
@ -272,42 +306,25 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCall32_64(context, null, nameof(SoftFallback.ReverseBytes32_64)); Operand d = context.Call(new _U64_U64(SoftFallback.ReverseBytes32_64), n);
}
}
private static void EmitCall32_64(EmitterContext context, string name32, string name64)
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(context, op.Rn);
Operand d;
if (op.RegisterSize == RegisterSize.Int32)
{
d = context.Call(typeof(SoftFallback).GetMethod(name32), n);
}
else
{
d = context.Call(typeof(SoftFallback).GetMethod(name64), n);
}
SetAluDOrZR(context, d); SetAluDOrZR(context, d);
} }
}
public static void Rev64(EmitterContext context) public static void Rev64(ArmEmitterContext context)
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(context, op.Rn))); SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(context, op.Rn)));
} }
public static void Rorv(EmitterContext context) public static void Rorv(ArmEmitterContext context)
{ {
SetAluDOrZR(context, context.RotateRight(GetAluN(context), GetAluMShift(context))); SetAluDOrZR(context, context.RotateRight(GetAluN(context), GetAluMShift(context)));
} }
private static Operand GetAluMShift(EmitterContext context) private static Operand GetAluMShift(ArmEmitterContext context)
{ {
IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp; IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp;
@ -321,29 +338,29 @@ namespace ARMeilleure.Instructions
return context.BitwiseAnd(m, Const(context.CurrOp.GetBitsCount() - 1)); return context.BitwiseAnd(m, Const(context.CurrOp.GetBitsCount() - 1));
} }
private static void EmitNZFlagsCheck(EmitterContext context, Operand d) private static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d)
{ {
context.Copy(GetFlag(PState.NFlag), context.ICompareLess (d, Const(d.Type, 0))); SetFlag(context, PState.NFlag, context.ICompareLess (d, Const(d.Type, 0)));
context.Copy(GetFlag(PState.ZFlag), context.ICompareEqual(d, Const(d.Type, 0))); SetFlag(context, PState.ZFlag, context.ICompareEqual(d, Const(d.Type, 0)));
} }
private static void EmitCVFlagsClear(EmitterContext context) private static void EmitCVFlagsClear(ArmEmitterContext context)
{ {
context.Copy(GetFlag(PState.CFlag), Const(0)); SetFlag(context, PState.CFlag, Const(0));
context.Copy(GetFlag(PState.VFlag), Const(0)); SetFlag(context, PState.VFlag, Const(0));
} }
public static void SetAluD(EmitterContext context, Operand d) public static void SetAluD(ArmEmitterContext context, Operand d)
{ {
SetAluD(context, d, x31IsZR: false); SetAluD(context, d, x31IsZR: false);
} }
public static void SetAluDOrZR(EmitterContext context, Operand d) public static void SetAluDOrZR(ArmEmitterContext context, Operand d)
{ {
SetAluD(context, d, x31IsZR: true); SetAluD(context, d, x31IsZR: true);
} }
public static void SetAluD(EmitterContext context, Operand d, bool x31IsZR) public static void SetAluD(ArmEmitterContext context, Operand d, bool x31IsZR)
{ {
IOpCodeAlu op = (IOpCodeAlu)context.CurrOp; IOpCodeAlu op = (IOpCodeAlu)context.CurrOp;

View file

@ -11,7 +11,7 @@ namespace ARMeilleure.Instructions
{ {
static class InstEmitAluHelper static class InstEmitAluHelper
{ {
public static void EmitAdcsCCheck(EmitterContext context, Operand n, Operand d) public static void EmitAdcsCCheck(ArmEmitterContext context, Operand n, Operand d)
{ {
//C = (Rd == Rn && CIn) || Rd < Rn //C = (Rd == Rn && CIn) || Rd < Rn
Operand cIn = GetFlag(PState.CFlag); Operand cIn = GetFlag(PState.CFlag);
@ -20,16 +20,16 @@ namespace ARMeilleure.Instructions
cOut = context.BitwiseOr(cOut, context.ICompareLessUI(d, n)); cOut = context.BitwiseOr(cOut, context.ICompareLessUI(d, n));
context.Copy(GetFlag(PState.CFlag), cOut); SetFlag(context, PState.CFlag, cOut);
} }
public static void EmitAddsCCheck(EmitterContext context, Operand n, Operand d) public static void EmitAddsCCheck(ArmEmitterContext context, Operand n, Operand d)
{ {
//C = Rd < Rn //C = Rd < Rn
context.Copy(GetFlag(PState.CFlag), context.ICompareLessUI(d, n)); SetFlag(context, PState.CFlag, context.ICompareLessUI(d, n));
} }
public static void EmitAddsVCheck(EmitterContext context, Operand n, Operand m, Operand d) public static void EmitAddsVCheck(ArmEmitterContext context, Operand n, Operand m, Operand d)
{ {
//V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0 //V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0
Operand vOut = context.BitwiseExclusiveOr(d, n); Operand vOut = context.BitwiseExclusiveOr(d, n);
@ -38,10 +38,10 @@ namespace ARMeilleure.Instructions
vOut = context.ICompareLess(vOut, Const(vOut.Type, 0)); vOut = context.ICompareLess(vOut, Const(vOut.Type, 0));
context.Copy(GetFlag(PState.VFlag), vOut); SetFlag(context, PState.VFlag, vOut);
} }
public static void EmitSbcsCCheck(EmitterContext context, Operand n, Operand m) public static void EmitSbcsCCheck(ArmEmitterContext context, Operand n, Operand m)
{ {
//C = (Rn == Rm && CIn) || Rn > Rm //C = (Rn == Rm && CIn) || Rn > Rm
Operand cIn = GetFlag(PState.CFlag); Operand cIn = GetFlag(PState.CFlag);
@ -50,16 +50,16 @@ namespace ARMeilleure.Instructions
cOut = context.BitwiseOr(cOut, context.ICompareGreaterUI(n, m)); cOut = context.BitwiseOr(cOut, context.ICompareGreaterUI(n, m));
context.Copy(GetFlag(PState.CFlag), cOut); SetFlag(context, PState.CFlag, cOut);
} }
public static void EmitSubsCCheck(EmitterContext context, Operand n, Operand m) public static void EmitSubsCCheck(ArmEmitterContext context, Operand n, Operand m)
{ {
//C = Rn >= Rm //C = Rn >= Rm
context.Copy(GetFlag(PState.CFlag), context.ICompareGreaterOrEqualUI(n, m)); SetFlag(context, PState.CFlag, context.ICompareGreaterOrEqualUI(n, m));
} }
public static void EmitSubsVCheck(EmitterContext context, Operand n, Operand m, Operand d) public static void EmitSubsVCheck(ArmEmitterContext context, Operand n, Operand m, Operand d)
{ {
//V = (Rd ^ Rn) & (Rn ^ Rm) < 0 //V = (Rd ^ Rn) & (Rn ^ Rm) < 0
Operand vOut = context.BitwiseExclusiveOr(d, n); Operand vOut = context.BitwiseExclusiveOr(d, n);
@ -68,10 +68,10 @@ namespace ARMeilleure.Instructions
vOut = context.ICompareLess(vOut, Const(vOut.Type, 0)); vOut = context.ICompareLess(vOut, Const(vOut.Type, 0));
context.Copy(GetFlag(PState.VFlag), vOut); SetFlag(context, PState.VFlag, vOut);
} }
public static Operand GetAluN(EmitterContext context) public static Operand GetAluN(ArmEmitterContext context)
{ {
if (context.CurrOp is IOpCodeAlu op) if (context.CurrOp is IOpCodeAlu op)
{ {
@ -94,7 +94,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static Operand GetAluM(EmitterContext context, bool setCarry = true) public static Operand GetAluM(ArmEmitterContext context, bool setCarry = true)
{ {
switch (context.CurrOp) switch (context.CurrOp)
{ {
@ -103,7 +103,7 @@ namespace ARMeilleure.Instructions
{ {
if (op.SetFlags && op.IsRotated) if (op.SetFlags && op.IsRotated)
{ {
context.Copy(GetFlag(PState.CFlag), Const((uint)op.Immediate >> 31)); SetFlag(context, PState.CFlag, Const((uint)op.Immediate >> 31));
} }
return Const(op.Immediate); return Const(op.Immediate);
@ -160,7 +160,7 @@ namespace ARMeilleure.Instructions
} }
//ARM32 helpers. //ARM32 helpers.
private static Operand GetMShiftedByImmediate(EmitterContext context, OpCode32AluRsImm op, bool setCarry) private static Operand GetMShiftedByImmediate(ArmEmitterContext context, OpCode32AluRsImm op, bool setCarry)
{ {
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -201,7 +201,7 @@ namespace ARMeilleure.Instructions
return m; return m;
} }
private static Operand GetLslC(EmitterContext context, Operand m, bool setCarry, int shift) private static Operand GetLslC(ArmEmitterContext context, Operand m, bool setCarry, int shift)
{ {
if ((uint)shift > 32) if ((uint)shift > 32)
{ {
@ -224,14 +224,14 @@ namespace ARMeilleure.Instructions
cOut = context.BitwiseAnd(cOut, Const(1)); cOut = context.BitwiseAnd(cOut, Const(1));
context.Copy(GetFlag(PState.CFlag), cOut); SetFlag(context, PState.CFlag, cOut);
} }
return context.ShiftLeft(m, Const(shift)); return context.ShiftLeft(m, Const(shift));
} }
} }
private static Operand GetLsrC(EmitterContext context, Operand m, bool setCarry, int shift) private static Operand GetLsrC(ArmEmitterContext context, Operand m, bool setCarry, int shift)
{ {
if ((uint)shift > 32) if ((uint)shift > 32)
{ {
@ -257,17 +257,17 @@ namespace ARMeilleure.Instructions
} }
} }
private static Operand GetShiftByMoreThan32(EmitterContext context, bool setCarry) private static Operand GetShiftByMoreThan32(ArmEmitterContext context, bool setCarry)
{ {
if (setCarry) if (setCarry)
{ {
context.Copy(GetFlag(PState.CFlag), Const(0));; SetFlag(context, PState.CFlag, Const(0));;
} }
return Const(0); return Const(0);
} }
private static Operand GetAsrC(EmitterContext context, Operand m, bool setCarry, int shift) private static Operand GetAsrC(ArmEmitterContext context, Operand m, bool setCarry, int shift)
{ {
if ((uint)shift >= 32) if ((uint)shift >= 32)
{ {
@ -291,7 +291,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static Operand GetRorC(EmitterContext context, Operand m, bool setCarry, int shift) private static Operand GetRorC(ArmEmitterContext context, Operand m, bool setCarry, int shift)
{ {
shift &= 0x1f; shift &= 0x1f;
@ -305,7 +305,7 @@ namespace ARMeilleure.Instructions
return m; return m;
} }
private static Operand GetRrxC(EmitterContext context, Operand m, bool setCarry) private static Operand GetRrxC(ArmEmitterContext context, Operand m, bool setCarry)
{ {
//Rotate right by 1 with carry. //Rotate right by 1 with carry.
Operand cIn = context.Copy(GetFlag(PState.CFlag)); Operand cIn = context.Copy(GetFlag(PState.CFlag));
@ -322,23 +322,23 @@ namespace ARMeilleure.Instructions
return m; return m;
} }
private static void SetCarryMLsb(EmitterContext context, Operand m) private static void SetCarryMLsb(ArmEmitterContext context, Operand m)
{ {
context.Copy(GetFlag(PState.CFlag), context.BitwiseAnd(m, Const(1))); SetFlag(context, PState.CFlag, context.BitwiseAnd(m, Const(1)));
} }
private static void SetCarryMMsb(EmitterContext context, Operand m) private static void SetCarryMMsb(ArmEmitterContext context, Operand m)
{ {
context.Copy(GetFlag(PState.CFlag), context.ShiftRightUI(m, Const(31))); SetFlag(context, PState.CFlag, context.ShiftRightUI(m, Const(31)));
} }
private static void SetCarryMShrOut(EmitterContext context, Operand m, int shift) private static void SetCarryMShrOut(ArmEmitterContext context, Operand m, int shift)
{ {
Operand cOut = context.ShiftRightUI(m, Const(shift - 1)); Operand cOut = context.ShiftRightUI(m, Const(shift - 1));
cOut = context.BitwiseAnd(cOut, Const(1)); cOut = context.BitwiseAnd(cOut, Const(1));
context.Copy(GetFlag(PState.CFlag), cOut); SetFlag(context, PState.CFlag, cOut);
} }
} }
} }

View file

@ -9,7 +9,7 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Bfm(EmitterContext context) public static void Bfm(ArmEmitterContext context)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
public static void Sbfm(EmitterContext context) public static void Sbfm(ArmEmitterContext context)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -94,7 +94,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ubfm(EmitterContext context) public static void Ubfm(ArmEmitterContext context)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -128,10 +128,10 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSbfiz(EmitterContext context) => EmitBfiz(context, signed: true); private static void EmitSbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: true);
private static void EmitUbfiz(EmitterContext context) => EmitBfiz(context, signed: false); private static void EmitUbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: false);
private static void EmitBfiz(EmitterContext context, bool signed) private static void EmitBfiz(ArmEmitterContext context, bool signed)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -148,17 +148,17 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
private static void EmitSbfmShift(EmitterContext context) private static void EmitSbfmShift(ArmEmitterContext context)
{ {
EmitBfmShift(context, signed: true); EmitBfmShift(context, signed: true);
} }
private static void EmitUbfmShift(EmitterContext context) private static void EmitUbfmShift(ArmEmitterContext context)
{ {
EmitBfmShift(context, signed: false); EmitBfmShift(context, signed: false);
} }
private static void EmitBfmShift(EmitterContext context, bool signed) private static void EmitBfmShift(ArmEmitterContext context, bool signed)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -171,7 +171,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
private static void EmitBfmLsl(EmitterContext context) private static void EmitBfmLsl(ArmEmitterContext context)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;
@ -182,7 +182,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, context.ShiftLeft(res, Const(shift))); SetIntOrZR(context, op.Rd, context.ShiftLeft(res, Const(shift)));
} }
private static Operand GetBfmN(EmitterContext context) private static Operand GetBfmN(ArmEmitterContext context)
{ {
OpCodeBfm op = (OpCodeBfm)context.CurrOp; OpCodeBfm op = (OpCodeBfm)context.CurrOp;

View file

@ -12,10 +12,10 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Ccmn(EmitterContext context) => EmitCcmp(context, isNegated: true); public static void Ccmn(ArmEmitterContext context) => EmitCcmp(context, isNegated: true);
public static void Ccmp(EmitterContext context) => EmitCcmp(context, isNegated: false); public static void Ccmp(ArmEmitterContext context) => EmitCcmp(context, isNegated: false);
private static void EmitCcmp(EmitterContext context, bool isNegated) private static void EmitCcmp(ArmEmitterContext context, bool isNegated)
{ {
OpCodeCcmp op = (OpCodeCcmp)context.CurrOp; OpCodeCcmp op = (OpCodeCcmp)context.CurrOp;
@ -24,10 +24,10 @@ namespace ARMeilleure.Instructions
EmitCondBranch(context, lblTrue, op.Cond); EmitCondBranch(context, lblTrue, op.Cond);
context.Copy(GetFlag(PState.VFlag), Const((op.Nzcv >> 0) & 1)); SetFlag(context, PState.VFlag, Const((op.Nzcv >> 0) & 1));
context.Copy(GetFlag(PState.CFlag), Const((op.Nzcv >> 1) & 1)); SetFlag(context, PState.CFlag, Const((op.Nzcv >> 1) & 1));
context.Copy(GetFlag(PState.ZFlag), Const((op.Nzcv >> 2) & 1)); SetFlag(context, PState.ZFlag, Const((op.Nzcv >> 2) & 1));
context.Copy(GetFlag(PState.NFlag), Const((op.Nzcv >> 3) & 1)); SetFlag(context, PState.NFlag, Const((op.Nzcv >> 3) & 1));
context.Branch(lblEnd); context.Branch(lblEnd);

View file

@ -18,12 +18,12 @@ namespace ARMeilleure.Instructions
Negate Negate
} }
public static void Csel(EmitterContext context) => EmitCsel(context, CselOperation.None); public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);
public static void Csinc(EmitterContext context) => EmitCsel(context, CselOperation.Increment); public static void Csinc(ArmEmitterContext context) => EmitCsel(context, CselOperation.Increment);
public static void Csinv(EmitterContext context) => EmitCsel(context, CselOperation.Invert); public static void Csinv(ArmEmitterContext context) => EmitCsel(context, CselOperation.Invert);
public static void Csneg(EmitterContext context) => EmitCsel(context, CselOperation.Negate); public static void Csneg(ArmEmitterContext context) => EmitCsel(context, CselOperation.Negate);
private static void EmitCsel(EmitterContext context, CselOperation cselOp) private static void EmitCsel(ArmEmitterContext context, CselOperation cselOp)
{ {
OpCodeCsel op = (OpCodeCsel)context.CurrOp; OpCodeCsel op = (OpCodeCsel)context.CurrOp;

View file

@ -9,10 +9,10 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Sdiv(EmitterContext context) => EmitDiv(context, unsigned: false); public static void Sdiv(ArmEmitterContext context) => EmitDiv(context, unsigned: false);
public static void Udiv(EmitterContext context) => EmitDiv(context, unsigned: true); public static void Udiv(ArmEmitterContext context) => EmitDiv(context, unsigned: true);
private static void EmitDiv(EmitterContext context, bool unsigned) private static void EmitDiv(ArmEmitterContext context, bool unsigned)
{ {
OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp; OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;

View file

@ -1,6 +1,6 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Reflection; using System;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -8,25 +8,23 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Brk(EmitterContext context) public static void Brk(ArmEmitterContext context)
{ {
EmitExceptionCall(context, nameof(NativeInterface.Break)); EmitExceptionCall(context, NativeInterface.Break);
} }
public static void Svc(EmitterContext context) public static void Svc(ArmEmitterContext context)
{ {
EmitExceptionCall(context, nameof(NativeInterface.SupervisorCall)); EmitExceptionCall(context, NativeInterface.SupervisorCall);
} }
private static void EmitExceptionCall(EmitterContext context, string mthdName) private static void EmitExceptionCall(ArmEmitterContext context, _Void_U64_S32 func)
{ {
OpCodeException op = (OpCodeException)context.CurrOp; OpCodeException op = (OpCodeException)context.CurrOp;
MethodInfo info = typeof(NativeInterface).GetMethod(mthdName);
context.StoreToContext(); context.StoreToContext();
context.Call(info, Const(op.Address), Const(op.Id)); context.Call(func, Const(op.Address), Const(op.Id));
context.LoadFromContext(); context.LoadFromContext();
@ -36,15 +34,15 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Und(EmitterContext context) public static void Und(ArmEmitterContext context)
{ {
OpCode op = context.CurrOp; OpCode op = context.CurrOp;
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)); Delegate dlg = new _Void_U64_S32(NativeInterface.Undefined);
context.StoreToContext(); context.StoreToContext();
context.Call(info, Const(op.Address), Const(op.RawOpCode)); context.Call(dlg, Const(op.Address), Const(op.RawOpCode));
context.LoadFromContext(); context.LoadFromContext();

View file

@ -11,7 +11,7 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void B(EmitterContext context) public static void B(ArmEmitterContext context)
{ {
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
@ -25,14 +25,14 @@ namespace ARMeilleure.Instructions
} }
} }
public static void B_Cond(EmitterContext context) public static void B_Cond(ArmEmitterContext context)
{ {
OpCodeBImmCond op = (OpCodeBImmCond)context.CurrOp; OpCodeBImmCond op = (OpCodeBImmCond)context.CurrOp;
EmitBranch(context, op.Cond); EmitBranch(context, op.Cond);
} }
public static void Bl(EmitterContext context) public static void Bl(ArmEmitterContext context)
{ {
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
@ -41,7 +41,7 @@ namespace ARMeilleure.Instructions
EmitCall(context, (ulong)op.Immediate); EmitCall(context, (ulong)op.Immediate);
} }
public static void Blr(EmitterContext context) public static void Blr(ArmEmitterContext context)
{ {
OpCodeBReg op = (OpCodeBReg)context.CurrOp; OpCodeBReg op = (OpCodeBReg)context.CurrOp;
@ -52,32 +52,32 @@ namespace ARMeilleure.Instructions
EmitVirtualCall(context, n); EmitVirtualCall(context, n);
} }
public static void Br(EmitterContext context) public static void Br(ArmEmitterContext context)
{ {
OpCodeBReg op = (OpCodeBReg)context.CurrOp; OpCodeBReg op = (OpCodeBReg)context.CurrOp;
EmitVirtualJump(context, GetIntOrZR(context, op.Rn)); EmitVirtualJump(context, GetIntOrZR(context, op.Rn));
} }
public static void Cbnz(EmitterContext context) => EmitCb(context, onNotZero: true); public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
public static void Cbz(EmitterContext context) => EmitCb(context, onNotZero: false); public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
private static void EmitCb(EmitterContext context, bool onNotZero) private static void EmitCb(ArmEmitterContext context, bool onNotZero)
{ {
OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp; OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp;
EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero); EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero);
} }
public static void Ret(EmitterContext context) public static void Ret(ArmEmitterContext context)
{ {
context.Return(GetIntOrZR(context, RegisterAlias.Lr)); context.Return(GetIntOrZR(context, RegisterAlias.Lr));
} }
public static void Tbnz(EmitterContext context) => EmitTb(context, onNotZero: true); public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
public static void Tbz(EmitterContext context) => EmitTb(context, onNotZero: false); public static void Tbz(ArmEmitterContext context) => EmitTb(context, onNotZero: false);
private static void EmitTb(EmitterContext context, bool onNotZero) private static void EmitTb(ArmEmitterContext context, bool onNotZero)
{ {
OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp; OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp;
@ -86,7 +86,7 @@ namespace ARMeilleure.Instructions
EmitBranch(context, value, onNotZero); EmitBranch(context, value, onNotZero);
} }
private static void EmitBranch(EmitterContext context, Condition cond) private static void EmitBranch(ArmEmitterContext context, Condition cond)
{ {
OpCodeBImm op = (OpCodeBImm)context.CurrOp; OpCodeBImm op = (OpCodeBImm)context.CurrOp;
@ -113,7 +113,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitBranch(EmitterContext context, Operand value, bool onNotZero) private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero)
{ {
OpCodeBImm op = (OpCodeBImm)context.CurrOp; OpCodeBImm op = (OpCodeBImm)context.CurrOp;

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.Instructions
{ {
static class InstEmitFlowHelper static class InstEmitFlowHelper
{ {
public static void EmitCondBranch(EmitterContext context, Operand target, Condition cond) public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
{ {
if (cond != Condition.Al) if (cond != Condition.Al)
{ {
@ -22,8 +22,15 @@ namespace ARMeilleure.Instructions
} }
} }
public static Operand GetCondTrue(EmitterContext context, Condition condition) public static Operand GetCondTrue(ArmEmitterContext context, Condition condition)
{ {
Operand cmpResult = context.TryGetComparisonResult(condition);
if (cmpResult != null)
{
return cmpResult;
}
Operand value = Const(1); Operand value = Const(1);
Operand Inverse(Operand val) Operand Inverse(Operand val)
@ -131,27 +138,27 @@ namespace ARMeilleure.Instructions
return value; return value;
} }
public static void EmitCall(EmitterContext context, ulong immediate) public static void EmitCall(ArmEmitterContext context, ulong immediate)
{ {
context.Return(Const(immediate)); context.Return(Const(immediate));
} }
public static void EmitVirtualCall(EmitterContext context, Operand target) public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
{ {
EmitVirtualCallOrJump(context, target, isJump: false); EmitVirtualCallOrJump(context, target, isJump: false);
} }
public static void EmitVirtualJump(EmitterContext context, Operand target) public static void EmitVirtualJump(ArmEmitterContext context, Operand target)
{ {
EmitVirtualCallOrJump(context, target, isJump: true); EmitVirtualCallOrJump(context, target, isJump: true);
} }
private static void EmitVirtualCallOrJump(EmitterContext context, Operand target, bool isJump) private static void EmitVirtualCallOrJump(ArmEmitterContext context, Operand target, bool isJump)
{ {
context.Return(target); context.Return(target);
} }
private static void EmitContinueOrReturnCheck(EmitterContext context, Operand retVal) private static void EmitContinueOrReturnCheck(ArmEmitterContext context, Operand retVal)
{ {
//Note: The return value of the called method will be placed //Note: The return value of the called method will be placed
//at the Stack, the return value is always a Int64 with the //at the Stack, the return value is always a Int64 with the

View file

@ -1,7 +1,7 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Reflection; using System;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
@ -9,56 +9,54 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Crc32b(EmitterContext context) public static void Crc32b(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32b)); EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32b));
} }
public static void Crc32h(EmitterContext context) public static void Crc32h(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32h)); EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32h));
} }
public static void Crc32w(EmitterContext context) public static void Crc32w(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32w)); EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32w));
} }
public static void Crc32x(EmitterContext context) public static void Crc32x(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32x)); EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32x));
} }
public static void Crc32cb(EmitterContext context) public static void Crc32cb(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32cb)); EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32cb));
} }
public static void Crc32ch(EmitterContext context) public static void Crc32ch(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32ch)); EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32ch));
} }
public static void Crc32cw(EmitterContext context) public static void Crc32cw(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32cw)); EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32cw));
} }
public static void Crc32cx(EmitterContext context) public static void Crc32cx(ArmEmitterContext context)
{ {
EmitCrc32Call(context, nameof(SoftFallback.Crc32cx)); EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32cx));
} }
private static void EmitCrc32Call(EmitterContext context, string name) private static void EmitCrc32Call(ArmEmitterContext context, Delegate dlg)
{ {
OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp; OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;
MethodInfo info = typeof(SoftFallback).GetMethod(name);
Operand n = GetIntOrZR(context, op.Rn); Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm); Operand m = GetIntOrZR(context, op.Rm);
Operand d = context.Call(info, n, m); Operand d = context.Call(dlg, n, m);
SetIntOrZR(context, op.Rd, d); SetIntOrZR(context, op.Rd, d);
} }

View file

@ -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.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -16,7 +15,7 @@ namespace ARMeilleure.Instructions
return op is OpCodeT16; return op is OpCodeT16;
} }
public static Operand GetExtendedM(EmitterContext context, int rm, IntType type) public static Operand GetExtendedM(ArmEmitterContext context, int rm, IntType type)
{ {
Operand value = GetIntOrZR(context, rm); Operand value = GetIntOrZR(context, rm);
@ -34,7 +33,7 @@ namespace ARMeilleure.Instructions
return value; return value;
} }
public static Operand GetIntA32(EmitterContext context, int register) public static Operand GetIntA32(ArmEmitterContext context, int register)
{ {
if (register == RegisterAlias.Aarch32Pc) if (register == RegisterAlias.Aarch32Pc)
{ {
@ -132,7 +131,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static Operand GetIntOrZR(EmitterContext context, int regIndex) public static Operand GetIntOrZR(ArmEmitterContext context, int regIndex)
{ {
if (regIndex == RegisterConsts.ZeroIndex) if (regIndex == RegisterConsts.ZeroIndex)
{ {
@ -146,9 +145,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static bool FullDebug = false; public static void SetIntOrZR(ArmEmitterContext context, int regIndex, Operand value)
public static void SetIntOrZR(EmitterContext context, int regIndex, Operand value)
{ {
if (regIndex == RegisterConsts.ZeroIndex) if (regIndex == RegisterConsts.ZeroIndex)
{ {
@ -158,7 +155,7 @@ namespace ARMeilleure.Instructions
SetIntOrSP(context, regIndex, value); SetIntOrSP(context, regIndex, value);
} }
public static Operand GetIntOrSP(EmitterContext context, int regIndex) public static Operand GetIntOrSP(ArmEmitterContext context, int regIndex)
{ {
Operand value = Register(regIndex, RegisterType.Integer, OperandType.I64); Operand value = Register(regIndex, RegisterType.Integer, OperandType.I64);
@ -170,7 +167,7 @@ namespace ARMeilleure.Instructions
return value; return value;
} }
public static void SetIntOrSP(EmitterContext context, int regIndex, Operand value) public static void SetIntOrSP(ArmEmitterContext context, int regIndex, Operand value)
{ {
Operand reg = Register(regIndex, RegisterType.Integer, OperandType.I64); Operand reg = Register(regIndex, RegisterType.Integer, OperandType.I64);
@ -191,5 +188,12 @@ namespace ARMeilleure.Instructions
{ {
return Register((int)stateFlag, RegisterType.Flag, OperandType.I32); return Register((int)stateFlag, RegisterType.Flag, OperandType.I32);
} }
public static void SetFlag(ArmEmitterContext context, PState stateFlag, Operand value)
{
context.Copy(GetFlag(stateFlag), value);
context.MarkFlagSet(stateFlag);
}
} }
} }

View file

@ -10,14 +10,14 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Adr(EmitterContext context) public static void Adr(ArmEmitterContext context)
{ {
OpCodeAdr op = (OpCodeAdr)context.CurrOp; OpCodeAdr op = (OpCodeAdr)context.CurrOp;
SetIntOrZR(context, op.Rd, Const(op.Address + (ulong)op.Immediate)); SetIntOrZR(context, op.Rd, Const(op.Address + (ulong)op.Immediate));
} }
public static void Adrp(EmitterContext context) public static void Adrp(ArmEmitterContext context)
{ {
OpCodeAdr op = (OpCodeAdr)context.CurrOp; OpCodeAdr op = (OpCodeAdr)context.CurrOp;
@ -26,10 +26,10 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, Const(address)); SetIntOrZR(context, op.Rd, Const(address));
} }
public static void Ldr(EmitterContext context) => EmitLdr(context, signed: false); public static void Ldr(ArmEmitterContext context) => EmitLdr(context, signed: false);
public static void Ldrs(EmitterContext context) => EmitLdr(context, signed: true); public static void Ldrs(ArmEmitterContext context) => EmitLdr(context, signed: true);
private static void EmitLdr(EmitterContext context, bool signed) private static void EmitLdr(ArmEmitterContext context, bool signed)
{ {
OpCodeMem op = (OpCodeMem)context.CurrOp; OpCodeMem op = (OpCodeMem)context.CurrOp;
@ -51,7 +51,7 @@ namespace ARMeilleure.Instructions
EmitWBackIfNeeded(context, address); EmitWBackIfNeeded(context, address);
} }
public static void Ldr_Literal(EmitterContext context) public static void Ldr_Literal(ArmEmitterContext context)
{ {
IOpCodeLit op = (IOpCodeLit)context.CurrOp; IOpCodeLit op = (IOpCodeLit)context.CurrOp;
@ -70,7 +70,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ldp(EmitterContext context) public static void Ldp(ArmEmitterContext context)
{ {
OpCodeMemPair op = (OpCodeMemPair)context.CurrOp; OpCodeMemPair op = (OpCodeMemPair)context.CurrOp;
@ -96,7 +96,7 @@ namespace ARMeilleure.Instructions
EmitWBackIfNeeded(context, address); EmitWBackIfNeeded(context, address);
} }
public static void Str(EmitterContext context) public static void Str(ArmEmitterContext context)
{ {
OpCodeMem op = (OpCodeMem)context.CurrOp; OpCodeMem op = (OpCodeMem)context.CurrOp;
@ -107,7 +107,7 @@ namespace ARMeilleure.Instructions
EmitWBackIfNeeded(context, address); EmitWBackIfNeeded(context, address);
} }
public static void Stp(EmitterContext context) public static void Stp(ArmEmitterContext context)
{ {
OpCodeMemPair op = (OpCodeMemPair)context.CurrOp; OpCodeMemPair op = (OpCodeMemPair)context.CurrOp;
@ -121,7 +121,7 @@ namespace ARMeilleure.Instructions
EmitWBackIfNeeded(context, address); EmitWBackIfNeeded(context, address);
} }
private static Operand GetAddress(EmitterContext context) private static Operand GetAddress(ArmEmitterContext context)
{ {
Operand address = null; Operand address = null;
@ -160,7 +160,7 @@ namespace ARMeilleure.Instructions
return address; return address;
} }
private static void EmitWBackIfNeeded(EmitterContext context, Operand address) private static void EmitWBackIfNeeded(ArmEmitterContext context, Operand address)
{ {
//Check whenever the current OpCode has post-indexed write back, if so write it. //Check whenever the current OpCode has post-indexed write back, if so write it.
if (context.CurrOp is OpCodeMemImm op && op.WBack) if (context.CurrOp is OpCodeMemImm op && op.WBack)

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -21,33 +20,31 @@ namespace ARMeilleure.Instructions
OrderedEx = Ordered | Exclusive OrderedEx = Ordered | Exclusive
} }
public static void Clrex(EmitterContext context) public static void Clrex(ArmEmitterContext context)
{ {
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ClearExclusive)); context.Call(new _Void(NativeInterface.ClearExclusive));
context.Call(info);
} }
public static void Dmb(EmitterContext context) => EmitBarrier(context); public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
public static void Dsb(EmitterContext context) => EmitBarrier(context); public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
public static void Ldar(EmitterContext context) => EmitLdr(context, AccessType.Ordered); public static void Ldar(ArmEmitterContext context) => EmitLdr(context, AccessType.Ordered);
public static void Ldaxr(EmitterContext context) => EmitLdr(context, AccessType.OrderedEx); public static void Ldaxr(ArmEmitterContext context) => EmitLdr(context, AccessType.OrderedEx);
public static void Ldxr(EmitterContext context) => EmitLdr(context, AccessType.Exclusive); public static void Ldxr(ArmEmitterContext context) => EmitLdr(context, AccessType.Exclusive);
public static void Ldxp(EmitterContext context) => EmitLdp(context, AccessType.Exclusive); public static void Ldxp(ArmEmitterContext context) => EmitLdp(context, AccessType.Exclusive);
public static void Ldaxp(EmitterContext context) => EmitLdp(context, AccessType.OrderedEx); public static void Ldaxp(ArmEmitterContext context) => EmitLdp(context, AccessType.OrderedEx);
private static void EmitLdr(EmitterContext context, AccessType accType) private static void EmitLdr(ArmEmitterContext context, AccessType accType)
{ {
EmitLoadEx(context, accType, pair: false); EmitLoadEx(context, accType, pair: false);
} }
private static void EmitLdp(EmitterContext context, AccessType accType) private static void EmitLdp(ArmEmitterContext context, AccessType accType)
{ {
EmitLoadEx(context, accType, pair: true); EmitLoadEx(context, accType, pair: true);
} }
private static void EmitLoadEx(EmitterContext context, AccessType accType, bool pair) private static void EmitLoadEx(ArmEmitterContext context, AccessType accType, bool pair)
{ {
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp; OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
@ -105,63 +102,61 @@ namespace ARMeilleure.Instructions
} }
private static Operand EmitLoad( private static Operand EmitLoad(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
bool exclusive, bool exclusive,
int size) int size)
{ {
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
if (exclusive) if (exclusive)
{ {
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.ReadByteExclusive); break; case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByteExclusive); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16Exclusive); break; case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16Exclusive); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32Exclusive); break; case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32Exclusive); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64Exclusive); break; case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64Exclusive); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128Exclusive); break; case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128Exclusive); break;
} }
} }
else else
{ {
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.ReadByte); break; case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break; case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break; case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break; case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break; case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
} }
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); return context.Call(fallbackMethodDlg, address);
return context.Call(info, address);
} }
public static void Pfrm(EmitterContext context) public static void Pfrm(ArmEmitterContext context)
{ {
//Memory Prefetch, execute as no-op. //Memory Prefetch, execute as no-op.
} }
public static void Stlr(EmitterContext context) => EmitStr(context, AccessType.Ordered); public static void Stlr(ArmEmitterContext context) => EmitStr(context, AccessType.Ordered);
public static void Stlxr(EmitterContext context) => EmitStr(context, AccessType.OrderedEx); public static void Stlxr(ArmEmitterContext context) => EmitStr(context, AccessType.OrderedEx);
public static void Stxr(EmitterContext context) => EmitStr(context, AccessType.Exclusive); public static void Stxr(ArmEmitterContext context) => EmitStr(context, AccessType.Exclusive);
public static void Stxp(EmitterContext context) => EmitStp(context, AccessType.Exclusive); public static void Stxp(ArmEmitterContext context) => EmitStp(context, AccessType.Exclusive);
public static void Stlxp(EmitterContext context) => EmitStp(context, AccessType.OrderedEx); public static void Stlxp(ArmEmitterContext context) => EmitStp(context, AccessType.OrderedEx);
private static void EmitStr(EmitterContext context, AccessType accType) private static void EmitStr(ArmEmitterContext context, AccessType accType)
{ {
EmitStoreEx(context, accType, pair: false); EmitStoreEx(context, accType, pair: false);
} }
private static void EmitStp(EmitterContext context, AccessType accType) private static void EmitStp(ArmEmitterContext context, AccessType accType)
{ {
EmitStoreEx(context, accType, pair: true); EmitStoreEx(context, accType, pair: true);
} }
private static void EmitStoreEx(EmitterContext context, AccessType accType, bool pair) private static void EmitStoreEx(ArmEmitterContext context, AccessType accType, bool pair)
{ {
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp; OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
@ -213,7 +208,7 @@ namespace ARMeilleure.Instructions
} }
private static Operand EmitStore( private static Operand EmitStore(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
Operand value, Operand value,
bool exclusive, bool exclusive,
@ -224,43 +219,39 @@ namespace ARMeilleure.Instructions
value = context.ConvertI64ToI32(value); value = context.ConvertI64ToI32(value);
} }
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
if (exclusive) if (exclusive)
{ {
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.WriteByteExclusive); break; case 0: fallbackMethodDlg = new _S32_U64_U8 (NativeInterface.WriteByteExclusive); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16Exclusive); break; case 1: fallbackMethodDlg = new _S32_U64_U16 (NativeInterface.WriteUInt16Exclusive); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32Exclusive); break; case 2: fallbackMethodDlg = new _S32_U64_U32 (NativeInterface.WriteUInt32Exclusive); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64Exclusive); break; case 3: fallbackMethodDlg = new _S32_U64_U64 (NativeInterface.WriteUInt64Exclusive); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128Exclusive); break; case 4: fallbackMethodDlg = new _S32_U64_V128(NativeInterface.WriteVector128Exclusive); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); return context.Call(fallbackMethodDlg, address, value);
return context.Call(info, address, value);
} }
else else
{ {
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.WriteByte); break; case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break; case 1: fallbackMethodDlg = new _Void_U64_U16 (NativeInterface.WriteUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break; case 2: fallbackMethodDlg = new _Void_U64_U32 (NativeInterface.WriteUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break; case 3: fallbackMethodDlg = new _Void_U64_U64 (NativeInterface.WriteUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break; case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); context.Call(fallbackMethodDlg, address, value);
context.Call(info, address, value);
return null; return null;
} }
} }
private static void EmitBarrier(EmitterContext context) private static void EmitBarrier(ArmEmitterContext context)
{ {
//Note: This barrier is most likely not necessary, and probably //Note: This barrier is most likely not necessary, and probably
//doesn't make any difference since we need to do a ton of stuff //doesn't make any difference since we need to do a ton of stuff

View file

@ -1,10 +1,8 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
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.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -20,22 +18,22 @@ namespace ARMeilleure.Instructions
Sx64 Sx64
} }
public static void EmitLoadZx(EmitterContext context, Operand address, int rt, int size) public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size)
{ {
EmitLoad(context, address, Extension.Zx, rt, size); EmitLoad(context, address, Extension.Zx, rt, size);
} }
public static void EmitLoadSx32(EmitterContext context, Operand address, int rt, int size) public static void EmitLoadSx32(ArmEmitterContext context, Operand address, int rt, int size)
{ {
EmitLoad(context, address, Extension.Sx32, rt, size); EmitLoad(context, address, Extension.Sx32, rt, size);
} }
public static void EmitLoadSx64(EmitterContext context, Operand address, int rt, int size) public static void EmitLoadSx64(ArmEmitterContext context, Operand address, int rt, int size)
{ {
EmitLoad(context, address, Extension.Sx64, rt, size); EmitLoad(context, address, Extension.Sx64, rt, size);
} }
private static void EmitLoad(EmitterContext context, Operand address, Extension ext, int rt, int size) private static void EmitLoad(ArmEmitterContext context, Operand address, Extension ext, int rt, int size)
{ {
bool isSimd = IsSimd(context); bool isSimd = IsSimd(context);
@ -74,7 +72,7 @@ namespace ARMeilleure.Instructions
} }
public static void EmitLoadSimd( public static void EmitLoadSimd(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
Operand vector, Operand vector,
int rt, int rt,
@ -84,7 +82,7 @@ namespace ARMeilleure.Instructions
EmitReadVector(context, address, vector, rt, elem, size); EmitReadVector(context, address, vector, rt, elem, size);
} }
public static void EmitStore(EmitterContext context, Operand address, int rt, int size) public static void EmitStore(ArmEmitterContext context, Operand address, int rt, int size)
{ {
bool isSimd = IsSimd(context); bool isSimd = IsSimd(context);
@ -104,7 +102,7 @@ namespace ARMeilleure.Instructions
} }
public static void EmitStoreSimd( public static void EmitStoreSimd(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
int rt, int rt,
int elem, int elem,
@ -113,14 +111,14 @@ namespace ARMeilleure.Instructions
EmitWriteVector(context, address, rt, elem, size); EmitWriteVector(context, address, rt, elem, size);
} }
private static bool IsSimd(EmitterContext context) private static bool IsSimd(ArmEmitterContext context)
{ {
return context.CurrOp is IOpCodeSimd && return context.CurrOp is IOpCodeSimd &&
!(context.CurrOp is OpCodeSimdMemMs || !(context.CurrOp is OpCodeSimdMemMs ||
context.CurrOp is OpCodeSimdMemSs); context.CurrOp is OpCodeSimdMemSs);
} }
private static void EmitReadInt(EmitterContext context, Operand address, int rt, int size) private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size)
{ {
Operand isUnalignedAddr = EmitAddressCheck(context, address, size); Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -167,7 +165,7 @@ namespace ARMeilleure.Instructions
} }
private static void EmitReadVector( private static void EmitReadVector(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
Operand vector, Operand vector,
int rt, int rt,
@ -222,12 +220,12 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
private static Operand VectorCreate(EmitterContext context, Operand value) private static Operand VectorCreate(ArmEmitterContext context, Operand value)
{ {
return context.VectorInsert(context.VectorZero(), value, 0); return context.VectorInsert(context.VectorZero(), value, 0);
} }
private static void EmitWriteInt(EmitterContext context, Operand address, int rt, int size) private static void EmitWriteInt(ArmEmitterContext context, Operand address, int rt, int size)
{ {
Operand isUnalignedAddr = EmitAddressCheck(context, address, size); Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -266,7 +264,7 @@ namespace ARMeilleure.Instructions
} }
private static void EmitWriteVector( private static void EmitWriteVector(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
int rt, int rt,
int elem, int elem,
@ -318,7 +316,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
private static Operand EmitAddressCheck(EmitterContext context, Operand address, int size) private static Operand EmitAddressCheck(ArmEmitterContext context, Operand address, int size)
{ {
long addressCheckMask = ~(context.Memory.AddressSpaceSize - 1); long addressCheckMask = ~(context.Memory.AddressSpaceSize - 1);
@ -327,7 +325,7 @@ namespace ARMeilleure.Instructions
return context.BitwiseAnd(address, Const(addressCheckMask)); return context.BitwiseAnd(address, Const(addressCheckMask));
} }
private static Operand EmitPtPointerLoad(EmitterContext context, Operand address, Operand lblFallbackPath) private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblFallbackPath)
{ {
Operand pte = Const(context.Memory.PageTable.ToInt64()); Operand pte = Const(context.Memory.PageTable.ToInt64());
@ -366,45 +364,41 @@ namespace ARMeilleure.Instructions
return physAddr; return physAddr;
} }
private static void EmitReadIntFallback(EmitterContext context, Operand address, int rt, int size) private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
{ {
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.ReadByte); break; case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break; case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break; case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break; case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); SetIntOrZR(context, rt, context.Call(fallbackMethodDlg, address));
SetIntOrZR(context, rt, context.Call(info, address));
} }
private static void EmitReadVectorFallback( private static void EmitReadVectorFallback(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
Operand vector, Operand vector,
int rt, int rt,
int elem, int elem,
int size) int size)
{ {
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.ReadByte); break; case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break; case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break; case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break; case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break; case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); Operand value = context.Call(fallbackMethodDlg, address);
Operand value = context.Call(info, address);
if (size < 3) if (size < 3)
{ {
@ -422,20 +416,18 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(rt), value); context.Copy(GetVec(rt), value);
} }
private static void EmitWriteIntFallback(EmitterContext context, Operand address, int rt, int size) private static void EmitWriteIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
{ {
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.WriteByte); break; case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break; case 1: fallbackMethodDlg = new _Void_U64_U16(NativeInterface.WriteUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break; case 2: fallbackMethodDlg = new _Void_U64_U32(NativeInterface.WriteUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break; case 3: fallbackMethodDlg = new _Void_U64_U64(NativeInterface.WriteUInt64); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
Operand value = GetIntOrZR(context, rt); Operand value = GetIntOrZR(context, rt);
if (size < 3) if (size < 3)
@ -443,29 +435,27 @@ namespace ARMeilleure.Instructions
value = context.ConvertI64ToI32(value); value = context.ConvertI64ToI32(value);
} }
context.Call(info, address, value); context.Call(fallbackMethodDlg, address, value);
} }
private static void EmitWriteVectorFallback( private static void EmitWriteVectorFallback(
EmitterContext context, ArmEmitterContext context,
Operand address, Operand address,
int rt, int rt,
int elem, int elem,
int size) int size)
{ {
string fallbackMethodName = null; Delegate fallbackMethodDlg = null;
switch (size) switch (size)
{ {
case 0: fallbackMethodName = nameof(NativeInterface.WriteByte); break; case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break; case 1: fallbackMethodDlg = new _Void_U64_U16 (NativeInterface.WriteUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break; case 2: fallbackMethodDlg = new _Void_U64_U32 (NativeInterface.WriteUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break; case 3: fallbackMethodDlg = new _Void_U64_U64 (NativeInterface.WriteUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break; case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
} }
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
Operand value = null; Operand value = null;
if (size < 4) if (size < 4)
@ -494,7 +484,7 @@ namespace ARMeilleure.Instructions
value = GetVec(rt); value = GetVec(rt);
} }
context.Call(info, address, value); context.Call(fallbackMethodDlg, address, value);
} }
} }
} }

View file

@ -9,7 +9,7 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Movk(EmitterContext context) public static void Movk(ArmEmitterContext context)
{ {
OpCodeMov op = (OpCodeMov)context.CurrOp; OpCodeMov op = (OpCodeMov)context.CurrOp;
@ -24,14 +24,14 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
public static void Movn(EmitterContext context) public static void Movn(ArmEmitterContext context)
{ {
OpCodeMov op = (OpCodeMov)context.CurrOp; OpCodeMov op = (OpCodeMov)context.CurrOp;
SetIntOrZR(context, op.Rd, Const(op.GetOperandType(), ~op.Immediate)); SetIntOrZR(context, op.Rd, Const(op.GetOperandType(), ~op.Immediate));
} }
public static void Movz(EmitterContext context) public static void Movz(ArmEmitterContext context)
{ {
OpCodeMov op = (OpCodeMov)context.CurrOp; OpCodeMov op = (OpCodeMov)context.CurrOp;

View file

@ -9,10 +9,10 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Madd(EmitterContext context) => EmitMul(context, isAdd: true); public static void Madd(ArmEmitterContext context) => EmitMul(context, isAdd: true);
public static void Msub(EmitterContext context) => EmitMul(context, isAdd: false); public static void Msub(ArmEmitterContext context) => EmitMul(context, isAdd: false);
private static void EmitMul(EmitterContext context, bool isAdd) private static void EmitMul(ArmEmitterContext context, bool isAdd)
{ {
OpCodeMul op = (OpCodeMul)context.CurrOp; OpCodeMul op = (OpCodeMul)context.CurrOp;
@ -27,10 +27,10 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
public static void Smaddl(EmitterContext context) => EmitMull(context, MullFlags.SignedAdd); public static void Smaddl(ArmEmitterContext context) => EmitMull(context, MullFlags.SignedAdd);
public static void Smsubl(EmitterContext context) => EmitMull(context, MullFlags.SignedSubtract); public static void Smsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.SignedSubtract);
public static void Umaddl(EmitterContext context) => EmitMull(context, MullFlags.Add); public static void Umaddl(ArmEmitterContext context) => EmitMull(context, MullFlags.Add);
public static void Umsubl(EmitterContext context) => EmitMull(context, MullFlags.Subtract); public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
[Flags] [Flags]
private enum MullFlags private enum MullFlags
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
SignedSubtract = Signed | Subtract SignedSubtract = Signed | Subtract
} }
private static void EmitMull(EmitterContext context, MullFlags flags) private static void EmitMull(ArmEmitterContext context, MullFlags flags)
{ {
OpCodeMul op = (OpCodeMul)context.CurrOp; OpCodeMul op = (OpCodeMul)context.CurrOp;
@ -73,7 +73,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
public static void Smulh(EmitterContext context) public static void Smulh(ArmEmitterContext context)
{ {
OpCodeMul op = (OpCodeMul)context.CurrOp; OpCodeMul op = (OpCodeMul)context.CurrOp;
@ -85,7 +85,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, d); SetIntOrZR(context, op.Rd, d);
} }
public static void Umulh(EmitterContext context) public static void Umulh(ArmEmitterContext context)
{ {
OpCodeMul op = (OpCodeMul)context.CurrOp; OpCodeMul op = (OpCodeMul)context.CurrOp;

File diff suppressed because it is too large Load diff

View file

@ -14,12 +14,12 @@ namespace ARMeilleure.Instructions
static partial class InstEmit static partial class InstEmit
{ {
public static void Cmeq_S(EmitterContext context) public static void Cmeq_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareEqual(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareEqual(op1, op2), scalar: true);
} }
public static void Cmeq_V(EmitterContext context) public static void Cmeq_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -54,12 +54,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmge_S(EmitterContext context) public static void Cmge_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqual(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqual(op1, op2), scalar: true);
} }
public static void Cmge_V(EmitterContext context) public static void Cmge_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse42) if (Optimizations.UseSse42)
{ {
@ -98,12 +98,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmgt_S(EmitterContext context) public static void Cmgt_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareGreater(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareGreater(op1, op2), scalar: true);
} }
public static void Cmgt_V(EmitterContext context) public static void Cmgt_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse42) if (Optimizations.UseSse42)
{ {
@ -138,12 +138,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmhi_S(EmitterContext context) public static void Cmhi_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterUI(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareGreaterUI(op1, op2), scalar: true);
} }
public static void Cmhi_V(EmitterContext context) public static void Cmhi_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -177,12 +177,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmhs_S(EmitterContext context) public static void Cmhs_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqualUI(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqualUI(op1, op2), scalar: true);
} }
public static void Cmhs_V(EmitterContext context) public static void Cmhs_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -212,12 +212,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmle_S(EmitterContext context) public static void Cmle_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareLessOrEqual(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareLessOrEqual(op1, op2), scalar: true);
} }
public static void Cmle_V(EmitterContext context) public static void Cmle_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse42) if (Optimizations.UseSse42)
{ {
@ -246,12 +246,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmlt_S(EmitterContext context) public static void Cmlt_S(ArmEmitterContext context)
{ {
EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: true); EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: true);
} }
public static void Cmlt_V(EmitterContext context) public static void Cmlt_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse42) if (Optimizations.UseSse42)
{ {
@ -276,27 +276,27 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Cmtst_S(EmitterContext context) public static void Cmtst_S(ArmEmitterContext context)
{ {
EmitCmtstOp(context, scalar: true); EmitCmtstOp(context, scalar: true);
} }
public static void Cmtst_V(EmitterContext context) public static void Cmtst_V(ArmEmitterContext context)
{ {
EmitCmtstOp(context, scalar: false); EmitCmtstOp(context, scalar: false);
} }
public static void Fccmp_S(EmitterContext context) public static void Fccmp_S(ArmEmitterContext context)
{ {
EmitFccmpOrFccmpe(context, signalNaNs: false); EmitFccmpOrFccmpe(context, signalNaNs: false);
} }
public static void Fccmpe_S(EmitterContext context) public static void Fccmpe_S(ArmEmitterContext context)
{ {
EmitFccmpOrFccmpe(context, signalNaNs: true); EmitFccmpOrFccmpe(context, signalNaNs: true);
} }
public static void Fcmeq_S(EmitterContext context) public static void Fcmeq_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -304,11 +304,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: true); EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: true);
} }
} }
public static void Fcmeq_V(EmitterContext context) public static void Fcmeq_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -316,11 +316,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: false); EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: false);
} }
} }
public static void Fcmge_S(EmitterContext context) public static void Fcmge_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -328,11 +328,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true); EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: true);
} }
} }
public static void Fcmge_V(EmitterContext context) public static void Fcmge_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -340,11 +340,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false); EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: false);
} }
} }
public static void Fcmgt_S(EmitterContext context) public static void Fcmgt_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -352,11 +352,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true); EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: true);
} }
} }
public static void Fcmgt_V(EmitterContext context) public static void Fcmgt_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -364,11 +364,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false); EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: false);
} }
} }
public static void Fcmle_S(EmitterContext context) public static void Fcmle_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -376,11 +376,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: true); EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: true);
} }
} }
public static void Fcmle_V(EmitterContext context) public static void Fcmle_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -388,11 +388,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: false); EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: false);
} }
} }
public static void Fcmlt_S(EmitterContext context) public static void Fcmlt_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -400,11 +400,11 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: true); EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: true);
} }
} }
public static void Fcmlt_V(EmitterContext context) public static void Fcmlt_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
{ {
@ -412,21 +412,21 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: false); EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: false);
} }
} }
public static void Fcmp_S(EmitterContext context) public static void Fcmp_S(ArmEmitterContext context)
{ {
EmitFcmpOrFcmpe(context, signalNaNs: false); EmitFcmpOrFcmpe(context, signalNaNs: false);
} }
public static void Fcmpe_S(EmitterContext context) public static void Fcmpe_S(ArmEmitterContext context)
{ {
EmitFcmpOrFcmpe(context, signalNaNs: true); EmitFcmpOrFcmpe(context, signalNaNs: true);
} }
public static void EmitFccmpOrFccmpe(EmitterContext context, bool signalNaNs) public static void EmitFccmpOrFccmpe(ArmEmitterContext context, bool signalNaNs)
{ {
OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp; OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp;
@ -446,7 +446,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
private static void EmitFcmpOrFcmpe(EmitterContext context, bool signalNaNs) private static void EmitFcmpOrFcmpe(ArmEmitterContext context, bool signalNaNs)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -474,10 +474,10 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Instruction.X86Comisseq, n, m); Operand zf = context.AddIntrinsicInt(Instruction.X86Comisseq, n, m);
Operand nf = context.AddIntrinsicInt(Instruction.X86Comisslt, n, m); Operand nf = context.AddIntrinsicInt(Instruction.X86Comisslt, n, m);
context.Copy(GetFlag(PState.VFlag), Const(0)); SetFlag(context, PState.VFlag, Const(0));
context.Copy(GetFlag(PState.CFlag), cf); SetFlag(context, PState.CFlag, cf);
context.Copy(GetFlag(PState.ZFlag), zf); SetFlag(context, PState.ZFlag, zf);
context.Copy(GetFlag(PState.NFlag), nf); SetFlag(context, PState.NFlag, nf);
} }
else /* if (op.Size == 1) */ else /* if (op.Size == 1) */
{ {
@ -491,20 +491,20 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Instruction.X86Comisdeq, n, m); Operand zf = context.AddIntrinsicInt(Instruction.X86Comisdeq, n, m);
Operand nf = context.AddIntrinsicInt(Instruction.X86Comisdlt, n, m); Operand nf = context.AddIntrinsicInt(Instruction.X86Comisdlt, n, m);
context.Copy(GetFlag(PState.VFlag), Const(0)); SetFlag(context, PState.VFlag, Const(0));
context.Copy(GetFlag(PState.CFlag), cf); SetFlag(context, PState.CFlag, cf);
context.Copy(GetFlag(PState.ZFlag), zf); SetFlag(context, PState.ZFlag, zf);
context.Copy(GetFlag(PState.NFlag), nf); SetFlag(context, PState.NFlag, nf);
} }
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lblNaN); context.MarkLabel(lblNaN);
context.Copy(GetFlag(PState.VFlag), Const(1)); SetFlag(context, PState.VFlag, Const(1));
context.Copy(GetFlag(PState.CFlag), Const(1)); SetFlag(context, PState.CFlag, Const(1));
context.Copy(GetFlag(PState.ZFlag), Const(0)); SetFlag(context, PState.ZFlag, Const(0));
context.Copy(GetFlag(PState.NFlag), Const(0)); SetFlag(context, PState.NFlag, Const(0));
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
@ -524,13 +524,17 @@ namespace ARMeilleure.Instructions
me = context.VectorExtract(type, GetVec(op.Rm), 0); me = context.VectorExtract(type, GetVec(op.Rm), 0);
} }
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs)); Delegate dlg = op.Size != 0
? (Delegate)new _S32_F64_F64_Bool(SoftFloat64.FPCompare)
: (Delegate)new _S32_F32_F32_Bool(SoftFloat32.FPCompare);
Operand nzcv = context.Call(dlg, ne, me, Const(signalNaNs));
EmitSetNzcv(context, nzcv); EmitSetNzcv(context, nzcv);
} }
} }
private static void EmitSetNzcv(EmitterContext context, Operand nzcv) private static void EmitSetNzcv(ArmEmitterContext context, Operand nzcv)
{ {
Operand Extract(Operand value, int bit) Operand Extract(Operand value, int bit)
{ {
@ -544,13 +548,13 @@ namespace ARMeilleure.Instructions
return value; return value;
} }
context.Copy(GetFlag(PState.VFlag), Extract(nzcv, 0)); SetFlag(context, PState.VFlag, Extract(nzcv, 0));
context.Copy(GetFlag(PState.CFlag), Extract(nzcv, 1)); SetFlag(context, PState.CFlag, Extract(nzcv, 1));
context.Copy(GetFlag(PState.ZFlag), Extract(nzcv, 2)); SetFlag(context, PState.ZFlag, Extract(nzcv, 2));
context.Copy(GetFlag(PState.NFlag), Extract(nzcv, 3)); SetFlag(context, PState.NFlag, Extract(nzcv, 3));
} }
private static void EmitCmpOp(EmitterContext context, Func2I emitCmp, bool scalar) private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -584,7 +588,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitCmtstOp(EmitterContext context, bool scalar) private static void EmitCmtstOp(ArmEmitterContext context, bool scalar)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -611,7 +615,11 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitCmpOpF(EmitterContext context, string name, bool scalar) private static void EmitCmpOpF(
ArmEmitterContext context,
_F32_F32_F32 f32,
_F64_F64_F64 f64,
bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -637,7 +645,7 @@ namespace ARMeilleure.Instructions
me = sizeF == 0 ? ConstF(0f) : ConstF(0d); me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
} }
Operand e = EmitSoftFloatCall(context, name, ne, me); Operand e = EmitSoftFloatCall(context, f32, f64, ne, me);
res = context.VectorInsert(res, e, index); res = context.VectorInsert(res, e, index);
} }
@ -653,7 +661,7 @@ namespace ARMeilleure.Instructions
} }
private static void EmitCmpSseOrSse2OpF( private static void EmitCmpSseOrSse2OpF(
EmitterContext context, ArmEmitterContext context,
CmpCondition cond, CmpCondition cond,
bool scalar, bool scalar,
bool isLeOrLt = false) bool isLeOrLt = false)

View file

@ -1,7 +1,6 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
@ -9,50 +8,42 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Aesd_V(EmitterContext context) public static void Aesd_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)); context.Copy(d, context.Call(new _V128_V128_V128(SoftFallback.Decrypt), d, n));
context.Copy(d, context.Call(info, d, n));
} }
public static void Aese_V(EmitterContext context) public static void Aese_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)); context.Copy(d, context.Call(new _V128_V128_V128(SoftFallback.Encrypt), d, n));
context.Copy(d, context.Call(info, d, n));
} }
public static void Aesimc_V(EmitterContext context) public static void Aesimc_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)); context.Copy(GetVec(op.Rd), context.Call(new _V128_V128(SoftFallback.InverseMixColumns), n));
context.Copy(GetVec(op.Rd), context.Call(info, n));
} }
public static void Aesmc_V(EmitterContext context) public static void Aesmc_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)); context.Copy(GetVec(op.Rd), context.Call(new _V128_V128(SoftFallback.MixColumns), n));
context.Copy(GetVec(op.Rd), context.Call(info, n));
} }
} }
} }

View file

@ -4,7 +4,6 @@ using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
@ -16,7 +15,7 @@ namespace ARMeilleure.Instructions
static partial class InstEmit static partial class InstEmit
{ {
public static void Fcvt_S(EmitterContext context) public static void Fcvt_S(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -62,9 +61,9 @@ namespace ARMeilleure.Instructions
{ {
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0); Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
MethodInfo info = typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)); Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);
Operand res = context.Call(info, ne); Operand res = context.Call(dlg, ne);
res = context.ZeroExtend16(OperandType.I64, res); res = context.ZeroExtend16(OperandType.I64, res);
@ -74,9 +73,9 @@ namespace ARMeilleure.Instructions
{ {
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1); Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
MethodInfo info = typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)); Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);
Operand res = context.Call(info, ne); Operand res = context.Call(dlg, ne);
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
@ -94,17 +93,17 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtas_Gp(EmitterContext context) public static void Fcvtas_Gp(ArmEmitterContext context)
{ {
EmitFcvt_s_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1)); EmitFcvt_s_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
} }
public static void Fcvtau_Gp(EmitterContext context) public static void Fcvtau_Gp(ArmEmitterContext context)
{ {
EmitFcvt_u_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1)); EmitFcvt_u_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
} }
public static void Fcvtl_V(EmitterContext context) public static void Fcvtl_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -142,9 +141,9 @@ namespace ARMeilleure.Instructions
{ {
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1); Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
MethodInfo info = typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)); Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);
Operand e = context.Call(info, ne); Operand e = context.Call(dlg, ne);
res = context.VectorInsert(res, e, index); res = context.VectorInsert(res, e, index);
} }
@ -162,17 +161,17 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtms_Gp(EmitterContext context) public static void Fcvtms_Gp(ArmEmitterContext context)
{ {
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1)); EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
} }
public static void Fcvtmu_Gp(EmitterContext context) public static void Fcvtmu_Gp(ArmEmitterContext context)
{ {
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1)); EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
} }
public static void Fcvtn_V(EmitterContext context) public static void Fcvtn_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -213,9 +212,9 @@ namespace ARMeilleure.Instructions
if (sizeF == 0) if (sizeF == 0)
{ {
MethodInfo info = typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)); Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);
Operand e = context.Call(info, ne); Operand e = context.Call(dlg, ne);
e = context.ZeroExtend16(OperandType.I64, e); e = context.ZeroExtend16(OperandType.I64, e);
@ -233,7 +232,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtns_S(EmitterContext context) public static void Fcvtns_S(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -245,7 +244,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtns_V(EmitterContext context) public static void Fcvtns_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -257,7 +256,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtnu_S(EmitterContext context) public static void Fcvtnu_S(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -269,7 +268,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtnu_V(EmitterContext context) public static void Fcvtnu_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -281,27 +280,27 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtps_Gp(EmitterContext context) public static void Fcvtps_Gp(ArmEmitterContext context)
{ {
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1)); EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
} }
public static void Fcvtpu_Gp(EmitterContext context) public static void Fcvtpu_Gp(ArmEmitterContext context)
{ {
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1)); EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
} }
public static void Fcvtzs_Gp(EmitterContext context) public static void Fcvtzs_Gp(ArmEmitterContext context)
{ {
EmitFcvt_s_Gp(context, (op1) => op1); EmitFcvt_s_Gp(context, (op1) => op1);
} }
public static void Fcvtzs_Gp_Fixed(EmitterContext context) public static void Fcvtzs_Gp_Fixed(ArmEmitterContext context)
{ {
EmitFcvtzs_Gp_Fixed(context); EmitFcvtzs_Gp_Fixed(context);
} }
public static void Fcvtzs_S(EmitterContext context) public static void Fcvtzs_S(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -313,7 +312,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtzs_V(EmitterContext context) public static void Fcvtzs_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -325,7 +324,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtzs_V_Fixed(EmitterContext context) public static void Fcvtzs_V_Fixed(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -337,17 +336,17 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtzu_Gp(EmitterContext context) public static void Fcvtzu_Gp(ArmEmitterContext context)
{ {
EmitFcvt_u_Gp(context, (op1) => op1); EmitFcvt_u_Gp(context, (op1) => op1);
} }
public static void Fcvtzu_Gp_Fixed(EmitterContext context) public static void Fcvtzu_Gp_Fixed(ArmEmitterContext context)
{ {
EmitFcvtzu_Gp_Fixed(context); EmitFcvtzu_Gp_Fixed(context);
} }
public static void Fcvtzu_S(EmitterContext context) public static void Fcvtzu_S(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -359,7 +358,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtzu_V(EmitterContext context) public static void Fcvtzu_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -371,7 +370,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcvtzu_V_Fixed(EmitterContext context) public static void Fcvtzu_V_Fixed(ArmEmitterContext context)
{ {
if (Optimizations.UseSse41) if (Optimizations.UseSse41)
{ {
@ -383,7 +382,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Scvtf_Gp(EmitterContext context) public static void Scvtf_Gp(ArmEmitterContext context)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -399,7 +398,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
public static void Scvtf_Gp_Fixed(EmitterContext context) public static void Scvtf_Gp_Fixed(ArmEmitterContext context)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -417,7 +416,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
public static void Scvtf_S(EmitterContext context) public static void Scvtf_S(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -437,7 +436,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Scvtf_V(EmitterContext context) public static void Scvtf_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -453,7 +452,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Scvtf_V_Fixed(EmitterContext context) public static void Scvtf_V_Fixed(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -470,7 +469,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ucvtf_Gp(EmitterContext context) public static void Ucvtf_Gp(ArmEmitterContext context)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -481,7 +480,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
public static void Ucvtf_Gp_Fixed(EmitterContext context) public static void Ucvtf_Gp_Fixed(ArmEmitterContext context)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -494,7 +493,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
public static void Ucvtf_S(EmitterContext context) public static void Ucvtf_S(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -514,7 +513,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ucvtf_V(EmitterContext context) public static void Ucvtf_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -530,7 +529,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ucvtf_V_Fixed(EmitterContext context) public static void Ucvtf_V_Fixed(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -547,7 +546,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitFcvtn(EmitterContext context, bool signed, bool scalar) private static void EmitFcvtn(ArmEmitterContext context, bool signed, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -570,25 +569,21 @@ namespace ARMeilleure.Instructions
if (sizeF == 0) if (sizeF == 0)
{ {
string name = signed Delegate dlg = signed
? nameof(SoftFallback.SatF32ToS32) ? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
: nameof(SoftFallback.SatF32ToU32); : (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
MethodInfo info = typeof(SoftFallback).GetMethod(name); e = context.Call(dlg, e);
e = context.Call(info, e);
e = context.ZeroExtend32(OperandType.I64, e); e = context.ZeroExtend32(OperandType.I64, e);
} }
else /* if (sizeF == 1) */ else /* if (sizeF == 1) */
{ {
string name = signed Delegate dlg = signed
? nameof(SoftFallback.SatF64ToS64) ? (Delegate)new _S64_F64(SoftFallback.SatF64ToS64)
: nameof(SoftFallback.SatF64ToU64); : (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
MethodInfo info = typeof(SoftFallback).GetMethod(name); e = context.Call(dlg, e);
e = context.Call(info, e);
} }
res = EmitVectorInsert(context, res, e, index, sizeI); res = EmitVectorInsert(context, res, e, index, sizeI);
@ -597,7 +592,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitFcvtz(EmitterContext context, bool signed, bool scalar) private static void EmitFcvtz(ArmEmitterContext context, bool signed, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -622,25 +617,21 @@ namespace ARMeilleure.Instructions
if (sizeF == 0) if (sizeF == 0)
{ {
string name = signed Delegate dlg = signed
? nameof(SoftFallback.SatF32ToS32) ? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
: nameof(SoftFallback.SatF32ToU32); : (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
MethodInfo info = typeof(SoftFallback).GetMethod(name); e = context.Call(dlg, e);
e = context.Call(info, e);
e = context.ZeroExtend32(OperandType.I64, e); e = context.ZeroExtend32(OperandType.I64, e);
} }
else /* if (sizeF == 1) */ else /* if (sizeF == 1) */
{ {
string name = signed Delegate dlg = signed
? nameof(SoftFallback.SatF64ToS64) ? (Delegate)new _S64_F64(SoftFallback.SatF64ToS64)
: nameof(SoftFallback.SatF64ToU64); : (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
MethodInfo info = typeof(SoftFallback).GetMethod(name); e = context.Call(dlg, e);
e = context.Call(info, e);
} }
res = EmitVectorInsert(context, res, e, index, sizeI); res = EmitVectorInsert(context, res, e, index, sizeI);
@ -649,17 +640,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitFcvt_s_Gp(EmitterContext context, Func1I emit) private static void EmitFcvt_s_Gp(ArmEmitterContext context, Func1I emit)
{ {
EmitFcvt___Gp(context, emit, signed: true); EmitFcvt___Gp(context, emit, signed: true);
} }
private static void EmitFcvt_u_Gp(EmitterContext context, Func1I emit) private static void EmitFcvt_u_Gp(ArmEmitterContext context, Func1I emit)
{ {
EmitFcvt___Gp(context, emit, signed: false); EmitFcvt___Gp(context, emit, signed: false);
} }
private static void EmitFcvt___Gp(EmitterContext context, Func1I emit, bool signed) private static void EmitFcvt___Gp(ArmEmitterContext context, Func1I emit, bool signed)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -674,17 +665,17 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
private static void EmitFcvtzs_Gp_Fixed(EmitterContext context) private static void EmitFcvtzs_Gp_Fixed(ArmEmitterContext context)
{ {
EmitFcvtz__Gp_Fixed(context, signed: true); EmitFcvtz__Gp_Fixed(context, signed: true);
} }
private static void EmitFcvtzu_Gp_Fixed(EmitterContext context) private static void EmitFcvtzu_Gp_Fixed(ArmEmitterContext context)
{ {
EmitFcvtz__Gp_Fixed(context, signed: false); EmitFcvtz__Gp_Fixed(context, signed: false);
} }
private static void EmitFcvtz__Gp_Fixed(EmitterContext context, bool signed) private static void EmitFcvtz__Gp_Fixed(ArmEmitterContext context, bool signed)
{ {
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
@ -699,7 +690,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, res); SetIntOrZR(context, op.Rd, res);
} }
private static void EmitVectorCvtf(EmitterContext context, bool signed) private static void EmitVectorCvtf(ArmEmitterContext context, bool signed)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -726,7 +717,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static int GetFBits(EmitterContext context) private static int GetFBits(ArmEmitterContext context)
{ {
if (context.CurrOp is OpCodeSimdShImm op) if (context.CurrOp is OpCodeSimdShImm op)
{ {
@ -736,7 +727,7 @@ namespace ARMeilleure.Instructions
return 0; return 0;
} }
private static Operand EmitFPConvert(EmitterContext context, Operand value, int size, bool signed) private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
{ {
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64); Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
Debug.Assert((uint)size < 2); Debug.Assert((uint)size < 2);
@ -754,7 +745,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static Operand EmitScalarFcvts(EmitterContext context, Operand value, int fBits) private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits)
{ {
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
@ -762,27 +753,23 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int32) if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{ {
string name = value.Type == OperandType.FP32 Delegate dlg = value.Type == OperandType.FP32
? nameof(SoftFallback.SatF32ToS32) ? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
: nameof(SoftFallback.SatF64ToS32); : (Delegate)new _S32_F64(SoftFallback.SatF64ToS32);
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, value);
return context.Call(info, value);
} }
else else
{ {
string name = value.Type == OperandType.FP32 Delegate dlg = value.Type == OperandType.FP32
? nameof(SoftFallback.SatF32ToS64) ? (Delegate)new _S64_F32(SoftFallback.SatF32ToS64)
: nameof(SoftFallback.SatF64ToS64); : (Delegate)new _S64_F64(SoftFallback.SatF64ToS64);
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, value);
return context.Call(info, value);
} }
} }
private static Operand EmitScalarFcvtu(EmitterContext context, Operand value, int fBits) private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
{ {
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
@ -790,27 +777,23 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int32) if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{ {
string name = value.Type == OperandType.FP32 Delegate dlg = value.Type == OperandType.FP32
? nameof(SoftFallback.SatF32ToU32) ? (Delegate)new _U32_F32(SoftFallback.SatF32ToU32)
: nameof(SoftFallback.SatF64ToU32); : (Delegate)new _U32_F64(SoftFallback.SatF64ToU32);
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, value);
return context.Call(info, value);
} }
else else
{ {
string name = value.Type == OperandType.FP32 Delegate dlg = value.Type == OperandType.FP32
? nameof(SoftFallback.SatF32ToU64) ? (Delegate)new _U64_F32(SoftFallback.SatF32ToU64)
: nameof(SoftFallback.SatF64ToU64); : (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, value);
return context.Call(info, value);
} }
} }
private static Operand EmitF2iFBitsMul(EmitterContext context, Operand value, int fBits) private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
{ {
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
@ -829,7 +812,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static Operand EmitI2fFBitsMul(EmitterContext context, Operand value, int fBits) private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits)
{ {
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
@ -848,7 +831,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSse41Fcvts(EmitterContext context, FPRoundingMode roundMode, bool scalar) private static void EmitSse41Fcvts(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -950,7 +933,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSse41Fcvtu(EmitterContext context, FPRoundingMode roundMode, bool scalar) private static void EmitSse41Fcvtu(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1087,7 +1070,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSse2Scvtf(EmitterContext context, bool scalar) private static void EmitSse2Scvtf(ArmEmitterContext context, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1119,7 +1102,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitSse2Ucvtf(EmitterContext context, bool scalar) private static void EmitSse2Ucvtf(ArmEmitterContext context, bool scalar)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1164,16 +1147,16 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static Operand EmitVectorLongExtract(EmitterContext context, int reg, int index, int size) private static Operand EmitVectorLongExtract(ArmEmitterContext context, int reg, int index, int size)
{ {
OperandType type = size == 3 ? OperandType.I64 : OperandType.I32; OperandType type = size == 3 ? OperandType.I64 : OperandType.I32;
return context.VectorExtract(type, GetVec(reg), index); return context.VectorExtract(type, GetVec(reg), index);
} }
private static Operand EmitVectorLongCreate(EmitterContext context, Operand low, Operand high) private static Operand EmitVectorLongCreate(ArmEmitterContext context, Operand low, Operand high)
{ {
Operand vector = context.Copy(Local(OperandType.V128), low); Operand vector = context.VectorCreateScalar(low);
vector = context.VectorInsert(vector, high, 1); vector = context.VectorInsert(vector, high, 1);

View file

@ -1,17 +1,15 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
#region "Sha1" #region "Sha1"
public static void Sha1c_V(EmitterContext context) public static void Sha1c_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -21,27 +19,23 @@ namespace ARMeilleure.Instructions
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)); Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashChoose), d, ne, m);
Operand res = context.Call(info, d, ne, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha1h_V(EmitterContext context) public static void Sha1h_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand ne = context.VectorExtract(OperandType.I32, GetVec(op.Rn), 0); Operand ne = context.VectorExtract(OperandType.I32, GetVec(op.Rn), 0);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)); Operand res = context.Call(new _U32_U32(SoftFallback.FixedRotate), ne);
Operand res = context.Call(info, ne);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha1m_V(EmitterContext context) public static void Sha1m_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -51,14 +45,12 @@ namespace ARMeilleure.Instructions
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)); Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashMajority), d, ne, m);
Operand res = context.Call(info, d, ne, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha1p_V(EmitterContext context) public static void Sha1p_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -68,14 +60,12 @@ namespace ARMeilleure.Instructions
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)); Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashParity), d, ne, m);
Operand res = context.Call(info, d, ne, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha1su0_V(EmitterContext context) public static void Sha1su0_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -83,30 +73,26 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)); Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.Sha1SchedulePart1), d, n, m);
Operand res = context.Call(info, d, n, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha1su1_V(EmitterContext context) public static void Sha1su1_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)); Operand res = context.Call(new _V128_V128_V128(SoftFallback.Sha1SchedulePart2), d, n);
Operand res = context.Call(info, d, n);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
#endregion #endregion
#region "Sha256" #region "Sha256"
public static void Sha256h_V(EmitterContext context) public static void Sha256h_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -114,14 +100,12 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)); Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.HashLower), d, n, m);
Operand res = context.Call(info, d, n, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha256h2_V(EmitterContext context) public static void Sha256h2_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -129,28 +113,24 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)); Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.HashUpper), d, n, m);
Operand res = context.Call(info, d, n, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha256su0_V(EmitterContext context) public static void Sha256su0_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)); Operand res = context.Call(new _V128_V128_V128(SoftFallback.Sha256SchedulePart1), d, n);
Operand res = context.Call(info, d, n);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sha256su1_V(EmitterContext context) public static void Sha256su1_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -158,9 +138,7 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm); Operand m = GetVec(op.Rm);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)); Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.Sha256SchedulePart2), d, n, m);
Operand res = context.Call(info, d, n, m);
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }

View file

@ -4,7 +4,6 @@ using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -142,48 +141,48 @@ namespace ARMeilleure.Instructions
return (8 << (op.Size + 1)) - op.Imm; return (8 << (op.Size + 1)) - op.Imm;
} }
public static Operand X86GetScalar(EmitterContext context, float value) public static Operand X86GetScalar(ArmEmitterContext context, float value)
{ {
return X86GetScalar(context, BitConverter.SingleToInt32Bits(value)); return X86GetScalar(context, BitConverter.SingleToInt32Bits(value));
} }
public static Operand X86GetScalar(EmitterContext context, double value) public static Operand X86GetScalar(ArmEmitterContext context, double value)
{ {
return X86GetScalar(context, BitConverter.DoubleToInt64Bits(value)); return X86GetScalar(context, BitConverter.DoubleToInt64Bits(value));
} }
public static Operand X86GetScalar(EmitterContext context, int value) public static Operand X86GetScalar(ArmEmitterContext context, int value)
{ {
return context.Copy(Local(OperandType.V128), Const(value)); return context.VectorCreateScalar(Const(value));
} }
public static Operand X86GetScalar(EmitterContext context, long value) public static Operand X86GetScalar(ArmEmitterContext context, long value)
{ {
return context.Copy(Local(OperandType.V128), Const(value)); return context.VectorCreateScalar(Const(value));
} }
public static Operand X86GetAllElements(EmitterContext context, float value) public static Operand X86GetAllElements(ArmEmitterContext context, float value)
{ {
return X86GetAllElements(context, BitConverter.SingleToInt32Bits(value)); return X86GetAllElements(context, BitConverter.SingleToInt32Bits(value));
} }
public static Operand X86GetAllElements(EmitterContext context, double value) public static Operand X86GetAllElements(ArmEmitterContext context, double value)
{ {
return X86GetAllElements(context, BitConverter.DoubleToInt64Bits(value)); return X86GetAllElements(context, BitConverter.DoubleToInt64Bits(value));
} }
public static Operand X86GetAllElements(EmitterContext context, int value) public static Operand X86GetAllElements(ArmEmitterContext context, int value)
{ {
Operand vector = context.Copy(Local(OperandType.V128), Const(value)); Operand vector = context.VectorCreateScalar(Const(value));
vector = context.AddIntrinsic(Instruction.X86Shufps, vector, vector, Const(0)); vector = context.AddIntrinsic(Instruction.X86Shufps, vector, vector, Const(0));
return vector; return vector;
} }
public static Operand X86GetAllElements(EmitterContext context, long value) public static Operand X86GetAllElements(ArmEmitterContext context, long value)
{ {
Operand vector = context.Copy(Local(OperandType.V128), Const(value)); Operand vector = context.VectorCreateScalar(Const(value));
vector = context.AddIntrinsic(Instruction.X86Movlhps, vector, vector); vector = context.AddIntrinsic(Instruction.X86Movlhps, vector, vector);
@ -203,10 +202,7 @@ namespace ARMeilleure.Instructions
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."); throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
} }
public static void EmitScalarUnaryOpF( public static void EmitScalarUnaryOpF(ArmEmitterContext context, Instruction inst32, Instruction inst64)
EmitterContext context,
Instruction inst32,
Instruction inst64)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -228,10 +224,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitScalarBinaryOpF( public static void EmitScalarBinaryOpF(ArmEmitterContext context, Instruction inst32, Instruction inst64)
EmitterContext context,
Instruction inst32,
Instruction inst64)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -254,10 +247,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorUnaryOpF( public static void EmitVectorUnaryOpF(ArmEmitterContext context, Instruction inst32, Instruction inst64)
EmitterContext context,
Instruction inst32,
Instruction inst64)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -275,10 +265,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpF( public static void EmitVectorBinaryOpF(ArmEmitterContext context, Instruction inst32, Instruction inst64)
EmitterContext context,
Instruction inst32,
Instruction inst64)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -297,79 +284,71 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static Operand EmitUnaryMathCall(EmitterContext context, string name, Operand n) public static Operand EmitUnaryMathCall(ArmEmitterContext context, _F32_F32 f32, _F64_F64 f64, Operand n)
{ {
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
int sizeF = op.Size & 1; return (op.Size & 1) == 0 ? context.Call(f32, n) : context.Call(f64, n);
MethodInfo info;
if (sizeF == 0)
{
info = typeof(MathF).GetMethod(name, new Type[] { typeof(float) });
}
else /* if (sizeF == 1) */
{
info = typeof(Math).GetMethod(name, new Type[] { typeof(double) });
} }
return context.Call(info, n); public static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
}
public static Operand EmitBinaryMathCall(EmitterContext context, string name, Operand n)
{ {
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
int sizeF = op.Size & 1; Delegate dlg;
MethodInfo info; if ((op.Size & 1) == 0)
if (sizeF == 0)
{ {
info = typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(float) }); dlg = new _F32_F32_MidpointRounding(MathF.Round);
} }
else /* if (sizeF == 1) */ else /* if ((op.Size & 1) == 1) */
{ {
info = typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(double) }); dlg = new _F64_F64_MidpointRounding(Math.Round);
} }
return context.Call(info, n); return context.Call(dlg, n, Const((int)roundMode));
} }
public static Operand EmitRoundMathCall(EmitterContext context, MidpointRounding roundMode, Operand n) public static Operand EmitSoftFloatCall(
ArmEmitterContext context,
_F32_F32 f32,
_F64_F64 f64,
params Operand[] callArgs)
{ {
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
int sizeF = op.Size & 1; Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
MethodInfo info; return context.Call(dlg, callArgs);
if (sizeF == 0)
{
info = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) });
}
else /* if (sizeF == 1) */
{
info = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) });
} }
return context.Call(info, n, Const((int)roundMode)); public static Operand EmitSoftFloatCall(
} ArmEmitterContext context,
_F32_F32_F32 f32,
public static Operand EmitSoftFloatCall(EmitterContext context, string name, params Operand[] callArgs) _F64_F64_F64 f64,
params Operand[] callArgs)
{ {
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
int sizeF = op.Size & 1; Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
Type type = sizeF == 0 ? typeof(SoftFloat32) return context.Call(dlg, callArgs);
: typeof(SoftFloat64);
return context.Call(type.GetMethod(name), callArgs);
} }
public static void EmitScalarBinaryOpByElemF(EmitterContext context, Func2I emit) public static Operand EmitSoftFloatCall(
ArmEmitterContext context,
_F32_F32_F32_F32 f32,
_F64_F64_F64_F64 f64,
params Operand[] callArgs)
{
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
return context.Call(dlg, callArgs);
}
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
@ -381,7 +360,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n, m), 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n, m), 0));
} }
public static void EmitScalarTernaryOpByElemF(EmitterContext context, Func3I emit) public static void EmitScalarTernaryOpByElemF(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
@ -394,7 +373,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(d, n, m), 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(d, n, m), 0));
} }
public static void EmitScalarUnaryOpSx(EmitterContext context, Func1I emit) public static void EmitScalarUnaryOpSx(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -405,7 +384,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitScalarBinaryOpSx(EmitterContext context, Func2I emit) public static void EmitScalarBinaryOpSx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -417,7 +396,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitScalarUnaryOpZx(EmitterContext context, Func1I emit) public static void EmitScalarUnaryOpZx(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -428,7 +407,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitScalarBinaryOpZx(EmitterContext context, Func2I emit) public static void EmitScalarBinaryOpZx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -440,7 +419,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitScalarTernaryOpZx(EmitterContext context, Func3I emit) public static void EmitScalarTernaryOpZx(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -453,7 +432,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitScalarUnaryOpF(EmitterContext context, Func1I emit) public static void EmitScalarUnaryOpF(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -464,7 +443,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n), 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n), 0));
} }
public static void EmitScalarBinaryOpF(EmitterContext context, Func2I emit) public static void EmitScalarBinaryOpF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -476,7 +455,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n, m), 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(n, m), 0));
} }
public static void EmitScalarTernaryRaOpF(EmitterContext context, Func3I emit) public static void EmitScalarTernaryRaOpF(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -489,7 +468,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(a, n, m), 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), emit(a, n, m), 0));
} }
public static void EmitVectorUnaryOpF(EmitterContext context, Func1I emit) public static void EmitVectorUnaryOpF(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -511,7 +490,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpF(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -534,7 +513,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorTernaryOpF(EmitterContext context, Func3I emit) public static void EmitVectorTernaryOpF(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -558,7 +537,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpByElemF(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
@ -581,7 +560,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorTernaryOpByElemF(EmitterContext context, Func3I emit) public static void EmitVectorTernaryOpByElemF(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
@ -605,7 +584,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorUnaryOpSx(EmitterContext context, Func1I emit) public static void EmitVectorUnaryOpSx(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -623,7 +602,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpSx(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpSx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -642,7 +621,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorTernaryOpSx(EmitterContext context, Func3I emit) public static void EmitVectorTernaryOpSx(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -662,7 +641,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorUnaryOpZx(EmitterContext context, Func1I emit) public static void EmitVectorUnaryOpZx(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -680,7 +659,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpZx(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpZx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -699,7 +678,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorTernaryOpZx(EmitterContext context, Func3I emit) public static void EmitVectorTernaryOpZx(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -719,7 +698,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpByElemSx(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpByElemSx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
@ -739,7 +718,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorBinaryOpByElemZx(EmitterContext context, Func2I emit) public static void EmitVectorBinaryOpByElemZx(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
@ -759,7 +738,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorTernaryOpByElemZx(EmitterContext context, Func3I emit) public static void EmitVectorTernaryOpByElemZx(ArmEmitterContext context, Func3I emit)
{ {
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
@ -780,7 +759,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorImmUnaryOp(EmitterContext context, Func1I emit) public static void EmitVectorImmUnaryOp(ArmEmitterContext context, Func1I emit)
{ {
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp; OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
@ -798,7 +777,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorImmBinaryOp(EmitterContext context, Func2I emit) public static void EmitVectorImmBinaryOp(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp; OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
@ -818,17 +797,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorWidenRmBinaryOpSx(EmitterContext context, Func2I emit) public static void EmitVectorWidenRmBinaryOpSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenRmBinaryOp(context, emit, signed: true); EmitVectorWidenRmBinaryOp(context, emit, signed: true);
} }
public static void EmitVectorWidenRmBinaryOpZx(EmitterContext context, Func2I emit) public static void EmitVectorWidenRmBinaryOpZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenRmBinaryOp(context, emit, signed: false); EmitVectorWidenRmBinaryOp(context, emit, signed: false);
} }
private static void EmitVectorWidenRmBinaryOp(EmitterContext context, Func2I emit, bool signed) private static void EmitVectorWidenRmBinaryOp(ArmEmitterContext context, Func2I emit, bool signed)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -849,17 +828,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorWidenRnRmBinaryOpSx(EmitterContext context, Func2I emit) public static void EmitVectorWidenRnRmBinaryOpSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenRnRmBinaryOp(context, emit, signed: true); EmitVectorWidenRnRmBinaryOp(context, emit, signed: true);
} }
public static void EmitVectorWidenRnRmBinaryOpZx(EmitterContext context, Func2I emit) public static void EmitVectorWidenRnRmBinaryOpZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenRnRmBinaryOp(context, emit, signed: false); EmitVectorWidenRnRmBinaryOp(context, emit, signed: false);
} }
private static void EmitVectorWidenRnRmBinaryOp(EmitterContext context, Func2I emit, bool signed) private static void EmitVectorWidenRnRmBinaryOp(ArmEmitterContext context, Func2I emit, bool signed)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -880,17 +859,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorWidenRnRmTernaryOpSx(EmitterContext context, Func3I emit) public static void EmitVectorWidenRnRmTernaryOpSx(ArmEmitterContext context, Func3I emit)
{ {
EmitVectorWidenRnRmTernaryOp(context, emit, signed: true); EmitVectorWidenRnRmTernaryOp(context, emit, signed: true);
} }
public static void EmitVectorWidenRnRmTernaryOpZx(EmitterContext context, Func3I emit) public static void EmitVectorWidenRnRmTernaryOpZx(ArmEmitterContext context, Func3I emit)
{ {
EmitVectorWidenRnRmTernaryOp(context, emit, signed: false); EmitVectorWidenRnRmTernaryOp(context, emit, signed: false);
} }
private static void EmitVectorWidenRnRmTernaryOp(EmitterContext context, Func3I emit, bool signed) private static void EmitVectorWidenRnRmTernaryOp(ArmEmitterContext context, Func3I emit, bool signed)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -912,17 +891,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorWidenBinaryOpByElemSx(EmitterContext context, Func2I emit) public static void EmitVectorWidenBinaryOpByElemSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenBinaryOpByElem(context, emit, signed: true); EmitVectorWidenBinaryOpByElem(context, emit, signed: true);
} }
public static void EmitVectorWidenBinaryOpByElemZx(EmitterContext context, Func2I emit) public static void EmitVectorWidenBinaryOpByElemZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorWidenBinaryOpByElem(context, emit, signed: false); EmitVectorWidenBinaryOpByElem(context, emit, signed: false);
} }
private static void EmitVectorWidenBinaryOpByElem(EmitterContext context, Func2I emit, bool signed) private static void EmitVectorWidenBinaryOpByElem(ArmEmitterContext context, Func2I emit, bool signed)
{ {
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
@ -944,17 +923,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorWidenTernaryOpByElemSx(EmitterContext context, Func3I emit) public static void EmitVectorWidenTernaryOpByElemSx(ArmEmitterContext context, Func3I emit)
{ {
EmitVectorWidenTernaryOpByElem(context, emit, signed: true); EmitVectorWidenTernaryOpByElem(context, emit, signed: true);
} }
public static void EmitVectorWidenTernaryOpByElemZx(EmitterContext context, Func3I emit) public static void EmitVectorWidenTernaryOpByElemZx(ArmEmitterContext context, Func3I emit)
{ {
EmitVectorWidenTernaryOpByElem(context, emit, signed: false); EmitVectorWidenTernaryOpByElem(context, emit, signed: false);
} }
private static void EmitVectorWidenTernaryOpByElem(EmitterContext context, Func3I emit, bool signed) private static void EmitVectorWidenTernaryOpByElem(ArmEmitterContext context, Func3I emit, bool signed)
{ {
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
@ -977,17 +956,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorPairwiseOpSx(EmitterContext context, Func2I emit) public static void EmitVectorPairwiseOpSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorPairwiseOp(context, emit, signed: true); EmitVectorPairwiseOp(context, emit, signed: true);
} }
public static void EmitVectorPairwiseOpZx(EmitterContext context, Func2I emit) public static void EmitVectorPairwiseOpZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorPairwiseOp(context, emit, signed: false); EmitVectorPairwiseOp(context, emit, signed: false);
} }
private static void EmitVectorPairwiseOp(EmitterContext context, Func2I emit, bool signed) private static void EmitVectorPairwiseOp(ArmEmitterContext context, Func2I emit, bool signed)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -1012,28 +991,28 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorAcrossVectorOpSx(EmitterContext context, Func2I emit) public static void EmitVectorAcrossVectorOpSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: false); EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: false);
} }
public static void EmitVectorAcrossVectorOpZx(EmitterContext context, Func2I emit) public static void EmitVectorAcrossVectorOpZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: false); EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: false);
} }
public static void EmitVectorLongAcrossVectorOpSx(EmitterContext context, Func2I emit) public static void EmitVectorLongAcrossVectorOpSx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: true); EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: true);
} }
public static void EmitVectorLongAcrossVectorOpZx(EmitterContext context, Func2I emit) public static void EmitVectorLongAcrossVectorOpZx(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: true); EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: true);
} }
private static void EmitVectorAcrossVectorOp( private static void EmitVectorAcrossVectorOp(
EmitterContext context, ArmEmitterContext context,
Func2I emit, Func2I emit,
bool signed, bool signed,
bool isLong) bool isLong)
@ -1058,7 +1037,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), d); context.Copy(GetVec(op.Rd), d);
} }
public static void EmitVectorPairwiseOpF(EmitterContext context, Func2I emit) public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -1087,7 +1066,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitVectorPairwiseOpF(EmitterContext context, Instruction inst32, Instruction inst64) public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Instruction inst32, Instruction inst64)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -1148,17 +1127,17 @@ namespace ARMeilleure.Instructions
VectorZx = 0 VectorZx = 0
} }
public static void EmitScalarSaturatingUnaryOpSx(EmitterContext context, Func1I emit) public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
{ {
EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.ScalarSx); EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.ScalarSx);
} }
public static void EmitVectorSaturatingUnaryOpSx(EmitterContext context, Func1I emit) public static void EmitVectorSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
{ {
EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.VectorSx); EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.VectorSx);
} }
private static void EmitSaturatingUnaryOpSx(EmitterContext context, Func1I emit, SaturatingFlags flags) private static void EmitSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit, SaturatingFlags flags)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1188,27 +1167,27 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void EmitScalarSaturatingBinaryOpSx(EmitterContext context, SaturatingFlags flags) public static void EmitScalarSaturatingBinaryOpSx(ArmEmitterContext context, SaturatingFlags flags)
{ {
EmitSaturatingBinaryOp(context, null, SaturatingFlags.ScalarSx | flags); EmitSaturatingBinaryOp(context, null, SaturatingFlags.ScalarSx | flags);
} }
public static void EmitScalarSaturatingBinaryOpZx(EmitterContext context, SaturatingFlags flags) public static void EmitScalarSaturatingBinaryOpZx(ArmEmitterContext context, SaturatingFlags flags)
{ {
EmitSaturatingBinaryOp(context, null, SaturatingFlags.ScalarZx | flags); EmitSaturatingBinaryOp(context, null, SaturatingFlags.ScalarZx | flags);
} }
public static void EmitVectorSaturatingBinaryOpSx(EmitterContext context, SaturatingFlags flags) public static void EmitVectorSaturatingBinaryOpSx(ArmEmitterContext context, SaturatingFlags flags)
{ {
EmitSaturatingBinaryOp(context, null, SaturatingFlags.VectorSx | flags); EmitSaturatingBinaryOp(context, null, SaturatingFlags.VectorSx | flags);
} }
public static void EmitVectorSaturatingBinaryOpZx(EmitterContext context, SaturatingFlags flags) public static void EmitVectorSaturatingBinaryOpZx(ArmEmitterContext context, SaturatingFlags flags)
{ {
EmitSaturatingBinaryOp(context, null, SaturatingFlags.VectorZx | flags); EmitSaturatingBinaryOp(context, null, SaturatingFlags.VectorZx | flags);
} }
public static void EmitSaturatingBinaryOp(EmitterContext context, Func2I emit, SaturatingFlags flags) public static void EmitSaturatingBinaryOp(ArmEmitterContext context, Func2I emit, SaturatingFlags flags)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1309,7 +1288,7 @@ namespace ARMeilleure.Instructions
VectorZxZx = 0 VectorZxZx = 0
} }
public static void EmitSaturatingNarrowOp(EmitterContext context, SaturatingNarrowFlags flags) public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -1336,83 +1315,86 @@ namespace ARMeilleure.Instructions
} }
// TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
public static Operand EmitSatQ(EmitterContext context, Operand op, int sizeDst, bool signedSrc, bool signedDst) public static Operand EmitSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedSrc, bool signedDst)
{ {
if ((uint)sizeDst > 2u) if ((uint)sizeDst > 2u)
{ {
throw new ArgumentOutOfRangeException(nameof(sizeDst)); throw new ArgumentOutOfRangeException(nameof(sizeDst));
} }
string name; Delegate dlg;
if (signedSrc) if (signedSrc)
{ {
name = signedDst ? nameof(SoftFallback.SignedSrcSignedDstSatQ) dlg = signedDst
: nameof(SoftFallback.SignedSrcUnsignedDstSatQ); ? (Delegate)new _S64_S64_S32(SoftFallback.SignedSrcSignedDstSatQ)
: (Delegate)new _U64_S64_S32(SoftFallback.SignedSrcUnsignedDstSatQ);
} }
else else
{ {
name = signedDst ? nameof(SoftFallback.UnsignedSrcSignedDstSatQ) dlg = signedDst
: nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ); ? (Delegate)new _S64_U64_S32(SoftFallback.UnsignedSrcSignedDstSatQ)
: (Delegate)new _U64_U64_S32(SoftFallback.UnsignedSrcUnsignedDstSatQ);
} }
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, op, Const(sizeDst));
return context.Call(info, op, Const(sizeDst));
} }
// TSrc (64bit) == TDst (64bit); signed. // TSrc (64bit) == TDst (64bit); signed.
public static Operand EmitUnarySignedSatQAbsOrNeg(EmitterContext context, Operand op) public static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op); return context.Call(new _S64_S64(SoftFallback.UnarySignedSatQAbsOrNeg), op);
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static Operand EmitBinarySatQAdd(EmitterContext context, Operand op1, Operand op2, bool signed) public static Operand EmitBinarySatQAdd(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
string name = signed ? nameof(SoftFallback.BinarySignedSatQAdd) Delegate dlg = signed
: nameof(SoftFallback.BinaryUnsignedSatQAdd); ? (Delegate)new _S64_S64_S64(SoftFallback.BinarySignedSatQAdd)
: (Delegate)new _U64_U64_U64(SoftFallback.BinaryUnsignedSatQAdd);
return context.Call(typeof(SoftFallback).GetMethod(name), op1, op2); return context.Call(dlg, op1, op2);
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static Operand EmitBinarySatQSub(EmitterContext context, Operand op1, Operand op2, bool signed) public static Operand EmitBinarySatQSub(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
string name = signed ? nameof(SoftFallback.BinarySignedSatQSub) Delegate dlg = signed
: nameof(SoftFallback.BinaryUnsignedSatQSub); ? (Delegate)new _S64_S64_S64(SoftFallback.BinarySignedSatQSub)
: (Delegate)new _U64_U64_U64(SoftFallback.BinaryUnsignedSatQSub);
return context.Call(typeof(SoftFallback).GetMethod(name), op1, op2); return context.Call(dlg, op1, op2);
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static Operand EmitBinarySatQAccumulate(EmitterContext context, Operand op1, Operand op2, bool signed) public static Operand EmitBinarySatQAccumulate(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
string name = signed ? nameof(SoftFallback.BinarySignedSatQAcc) Delegate dlg = signed
: nameof(SoftFallback.BinaryUnsignedSatQAcc); ? (Delegate)new _S64_U64_S64(SoftFallback.BinarySignedSatQAcc)
: (Delegate)new _U64_S64_U64(SoftFallback.BinaryUnsignedSatQAcc);
return context.Call(typeof(SoftFallback).GetMethod(name), op1, op2); return context.Call(dlg, op1, op2);
} }
public static Operand EmitVectorExtractSx(EmitterContext context, int reg, int index, int size) public static Operand EmitVectorExtractSx(ArmEmitterContext context, int reg, int index, int size)
{ {
return EmitVectorExtract(context, reg, index, size, true); return EmitVectorExtract(context, reg, index, size, true);
} }
public static Operand EmitVectorExtractZx(EmitterContext context, int reg, int index, int size) public static Operand EmitVectorExtractZx(ArmEmitterContext context, int reg, int index, int size)
{ {
return EmitVectorExtract(context, reg, index, size, false); return EmitVectorExtract(context, reg, index, size, false);
} }
public static Operand EmitVectorExtract(EmitterContext context, int reg, int index, int size, bool signed) public static Operand EmitVectorExtract(ArmEmitterContext context, int reg, int index, int size, bool signed)
{ {
ThrowIfInvalid(index, size); ThrowIfInvalid(index, size);
@ -1459,7 +1441,7 @@ namespace ARMeilleure.Instructions
return res; return res;
} }
public static Operand EmitVectorInsert(EmitterContext context, Operand vector, Operand value, int index, int size) public static Operand EmitVectorInsert(ArmEmitterContext context, Operand vector, Operand value, int index, int size)
{ {
ThrowIfInvalid(index, size); ThrowIfInvalid(index, size);

View file

@ -1,7 +1,6 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
@ -11,7 +10,7 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void And_V(EmitterContext context) public static void And_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -35,7 +34,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Bic_V(EmitterContext context) public static void Bic_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -62,7 +61,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Bic_Vi(EmitterContext context) public static void Bic_Vi(ArmEmitterContext context)
{ {
EmitVectorImmBinaryOp(context, (op1, op2) => EmitVectorImmBinaryOp(context, (op1, op2) =>
{ {
@ -70,17 +69,17 @@ namespace ARMeilleure.Instructions
}); });
} }
public static void Bif_V(EmitterContext context) public static void Bif_V(ArmEmitterContext context)
{ {
EmitBifBit(context, notRm: true); EmitBifBit(context, notRm: true);
} }
public static void Bit_V(EmitterContext context) public static void Bit_V(ArmEmitterContext context)
{ {
EmitBifBit(context, notRm: false); EmitBifBit(context, notRm: false);
} }
private static void EmitBifBit(EmitterContext context, bool notRm) private static void EmitBifBit(ArmEmitterContext context, bool notRm)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -139,7 +138,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Bsl_V(EmitterContext context) public static void Bsl_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -172,7 +171,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Eor_V(EmitterContext context) public static void Eor_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -196,7 +195,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Not_V(EmitterContext context) public static void Not_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -221,7 +220,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Orn_V(EmitterContext context) public static void Orn_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -252,7 +251,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Orr_V(EmitterContext context) public static void Orr_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -276,12 +275,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Orr_Vi(EmitterContext context) public static void Orr_Vi(ArmEmitterContext context)
{ {
EmitVectorImmBinaryOp(context, (op1, op2) => context.BitwiseOr(op1, op2)); EmitVectorImmBinaryOp(context, (op1, op2) => context.BitwiseOr(op1, op2));
} }
public static void Rbit_V(EmitterContext context) public static void Rbit_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -295,9 +294,7 @@ namespace ARMeilleure.Instructions
ne = context.ConvertI64ToI32(ne); ne = context.ConvertI64ToI32(ne);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.ReverseBits8)); Operand de = context.Call(new _U32_U32(SoftFallback.ReverseBits8), ne);
Operand de = context.Call(info, ne);
de = context.ZeroExtend32(OperandType.I64, de); de = context.ZeroExtend32(OperandType.I64, de);
@ -307,7 +304,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Rev16_V(EmitterContext context) public static void Rev16_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSsse3) if (Optimizations.UseSsse3)
{ {
@ -337,7 +334,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Rev32_V(EmitterContext context) public static void Rev32_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSsse3) if (Optimizations.UseSsse3)
{ {
@ -381,7 +378,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Rev64_V(EmitterContext context) public static void Rev64_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSsse3) if (Optimizations.UseSsse3)
{ {
@ -434,7 +431,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitRev_V(EmitterContext context, int containerSize) private static void EmitRev_V(ArmEmitterContext context, int containerSize)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;

View file

@ -12,27 +12,27 @@ namespace ARMeilleure.Instructions
{ {
static partial class InstEmit static partial class InstEmit
{ {
public static void Ld__Vms(EmitterContext context) public static void Ld__Vms(ArmEmitterContext context)
{ {
EmitSimdMemMs(context, isLoad: true); EmitSimdMemMs(context, isLoad: true);
} }
public static void Ld__Vss(EmitterContext context) public static void Ld__Vss(ArmEmitterContext context)
{ {
EmitSimdMemSs(context, isLoad: true); EmitSimdMemSs(context, isLoad: true);
} }
public static void St__Vms(EmitterContext context) public static void St__Vms(ArmEmitterContext context)
{ {
EmitSimdMemMs(context, isLoad: false); EmitSimdMemMs(context, isLoad: false);
} }
public static void St__Vss(EmitterContext context) public static void St__Vss(ArmEmitterContext context)
{ {
EmitSimdMemSs(context, isLoad: false); EmitSimdMemSs(context, isLoad: false);
} }
private static void EmitSimdMemMs(EmitterContext context, bool isLoad) private static void EmitSimdMemMs(ArmEmitterContext context, bool isLoad)
{ {
OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp; OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp;
@ -73,7 +73,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSimdMemSs(EmitterContext context, bool isLoad) private static void EmitSimdMemSs(ArmEmitterContext context, bool isLoad)
{ {
OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp; OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp;
@ -138,7 +138,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSimdMemWBack(EmitterContext context, long offset) private static void EmitSimdMemWBack(ArmEmitterContext context, long offset)
{ {
OpCodeMemReg op = (OpCodeMemReg)context.CurrOp; OpCodeMemReg op = (OpCodeMemReg)context.CurrOp;

View file

@ -1,6 +1,7 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
@ -38,7 +39,7 @@ namespace ARMeilleure.Instructions
}; };
#endregion #endregion
public static void Dup_Gp(EmitterContext context) public static void Dup_Gp(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -88,7 +89,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Dup_S(EmitterContext context) public static void Dup_S(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -97,7 +98,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), ne, 0, op.Size)); context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), ne, 0, op.Size));
} }
public static void Dup_V(EmitterContext context) public static void Dup_V(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -165,7 +166,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ext_V(EmitterContext context) public static void Ext_V(ArmEmitterContext context)
{ {
OpCodeSimdExt op = (OpCodeSimdExt)context.CurrOp; OpCodeSimdExt op = (OpCodeSimdExt)context.CurrOp;
@ -216,7 +217,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fcsel_S(EmitterContext context) public static void Fcsel_S(ArmEmitterContext context)
{ {
OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp; OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp;
@ -244,7 +245,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
public static void Fmov_Ftoi(EmitterContext context) public static void Fmov_Ftoi(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -253,7 +254,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, ne); SetIntOrZR(context, op.Rd, ne);
} }
public static void Fmov_Ftoi1(EmitterContext context) public static void Fmov_Ftoi1(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -262,7 +263,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, ne); SetIntOrZR(context, op.Rd, ne);
} }
public static void Fmov_Itof(EmitterContext context) public static void Fmov_Itof(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -271,7 +272,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, op.Size + 2)); context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, op.Size + 2));
} }
public static void Fmov_Itof1(EmitterContext context) public static void Fmov_Itof1(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -280,7 +281,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, GetVec(op.Rd), n, 1, 3)); context.Copy(GetVec(op.Rd), EmitVectorInsert(context, GetVec(op.Rd), n, 1, 3));
} }
public static void Fmov_S(EmitterContext context) public static void Fmov_S(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -291,7 +292,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), ne, 0)); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), ne, 0));
} }
public static void Fmov_Si(EmitterContext context) public static void Fmov_Si(ArmEmitterContext context)
{ {
OpCodeSimdFmov op = (OpCodeSimdFmov)context.CurrOp; OpCodeSimdFmov op = (OpCodeSimdFmov)context.CurrOp;
@ -305,7 +306,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fmov_Vi(EmitterContext context) public static void Fmov_Vi(ArmEmitterContext context)
{ {
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp; OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
@ -323,7 +324,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Ins_Gp(EmitterContext context) public static void Ins_Gp(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -333,7 +334,7 @@ namespace ARMeilleure.Instructions
context.Copy(d, EmitVectorInsert(context, d, n, op.DstIndex, op.Size)); context.Copy(d, EmitVectorInsert(context, d, n, op.DstIndex, op.Size));
} }
public static void Ins_V(EmitterContext context) public static void Ins_V(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -343,7 +344,7 @@ namespace ARMeilleure.Instructions
context.Copy(d, EmitVectorInsert(context, d, ne, op.DstIndex, op.Size)); context.Copy(d, EmitVectorInsert(context, d, ne, op.DstIndex, op.Size));
} }
public static void Movi_V(EmitterContext context) public static void Movi_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -355,7 +356,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Mvni_V(EmitterContext context) public static void Mvni_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSse2) if (Optimizations.UseSse2)
{ {
@ -367,7 +368,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Smov_S(EmitterContext context) public static void Smov_S(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -381,7 +382,7 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, ne); SetIntOrZR(context, op.Rd, ne);
} }
public static void Tbl_V(EmitterContext context) public static void Tbl_V(ArmEmitterContext context)
{ {
OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp; OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp;
@ -433,42 +434,42 @@ namespace ARMeilleure.Instructions
args[1 + index] = GetVec((op.Rn + index) & 0x1f); args[1 + index] = GetVec((op.Rn + index) & 0x1f);
} }
string name = null; Delegate dlg = null;
switch (op.Size) switch (op.Size)
{ {
case 1: name = op.RegisterSize == RegisterSize.Simd64 case 1: dlg = op.RegisterSize == RegisterSize.Simd64
? nameof(SoftFallback.Tbl1_V64) ? (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V64)
: nameof(SoftFallback.Tbl1_V128); break; : (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V128); break;
case 2: name = op.RegisterSize == RegisterSize.Simd64 case 2: dlg = op.RegisterSize == RegisterSize.Simd64
? nameof(SoftFallback.Tbl2_V64) ? (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V64)
: nameof(SoftFallback.Tbl2_V128); break; : (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V128); break;
case 3: name = op.RegisterSize == RegisterSize.Simd64 case 3: dlg = op.RegisterSize == RegisterSize.Simd64
? nameof(SoftFallback.Tbl3_V64) ? (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V64)
: nameof(SoftFallback.Tbl3_V128); break; : (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V128); break;
case 4: name = op.RegisterSize == RegisterSize.Simd64 case 4: dlg = op.RegisterSize == RegisterSize.Simd64
? nameof(SoftFallback.Tbl4_V64) ? (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V64)
: nameof(SoftFallback.Tbl4_V128); break; : (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V128); break;
} }
context.Copy(GetVec(op.Rd), context.Call(typeof(SoftFallback).GetMethod(name), args)); context.Copy(GetVec(op.Rd), context.Call(dlg, args));
} }
} }
public static void Trn1_V(EmitterContext context) public static void Trn1_V(ArmEmitterContext context)
{ {
EmitVectorTranspose(context, part: 0); EmitVectorTranspose(context, part: 0);
} }
public static void Trn2_V(EmitterContext context) public static void Trn2_V(ArmEmitterContext context)
{ {
EmitVectorTranspose(context, part: 1); EmitVectorTranspose(context, part: 1);
} }
public static void Umov_S(EmitterContext context) public static void Umov_S(ArmEmitterContext context)
{ {
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp; OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
@ -477,17 +478,17 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, ne); SetIntOrZR(context, op.Rd, ne);
} }
public static void Uzp1_V(EmitterContext context) public static void Uzp1_V(ArmEmitterContext context)
{ {
EmitVectorUnzip(context, part: 0); EmitVectorUnzip(context, part: 0);
} }
public static void Uzp2_V(EmitterContext context) public static void Uzp2_V(ArmEmitterContext context)
{ {
EmitVectorUnzip(context, part: 1); EmitVectorUnzip(context, part: 1);
} }
public static void Xtn_V(EmitterContext context) public static void Xtn_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -530,17 +531,17 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Zip1_V(EmitterContext context) public static void Zip1_V(ArmEmitterContext context)
{ {
EmitVectorZip(context, part: 0); EmitVectorZip(context, part: 0);
} }
public static void Zip2_V(EmitterContext context) public static void Zip2_V(ArmEmitterContext context)
{ {
EmitVectorZip(context, part: 1); EmitVectorZip(context, part: 1);
} }
private static void EmitMoviMvni(EmitterContext context, bool not) private static void EmitMoviMvni(ArmEmitterContext context, bool not)
{ {
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp; OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
@ -576,7 +577,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), mask); context.Copy(GetVec(op.Rd), mask);
} }
private static void EmitVectorTranspose(EmitterContext context, int part) private static void EmitVectorTranspose(ArmEmitterContext context, int part)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -642,7 +643,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitVectorUnzip(EmitterContext context, int part) private static void EmitVectorUnzip(ArmEmitterContext context, int part)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -735,7 +736,7 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitVectorZip(EmitterContext context, int part) private static void EmitVectorZip(ArmEmitterContext context, int part)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

View file

@ -4,7 +4,6 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
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;
@ -25,7 +24,7 @@ namespace ARMeilleure.Instructions
}; };
#endregion #endregion
public static void Rshrn_V(EmitterContext context) public static void Rshrn_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSsse3) if (Optimizations.UseSsse3)
{ {
@ -75,7 +74,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Shl_S(EmitterContext context) public static void Shl_S(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -84,7 +83,7 @@ namespace ARMeilleure.Instructions
EmitScalarUnaryOpZx(context, (op1) => context.ShiftLeft(op1, Const(shift))); EmitScalarUnaryOpZx(context, (op1) => context.ShiftLeft(op1, Const(shift)));
} }
public static void Shl_V(EmitterContext context) public static void Shl_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -111,7 +110,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Shll_V(EmitterContext context) public static void Shll_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -142,7 +141,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Shrn_V(EmitterContext context) public static void Shrn_V(ArmEmitterContext context)
{ {
if (Optimizations.UseSsse3) if (Optimizations.UseSsse3)
{ {
@ -179,7 +178,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Sli_V(EmitterContext context) public static void Sli_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -209,7 +208,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sqrshl_V(EmitterContext context) public static void Sqrshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -222,9 +221,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)); Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -232,27 +229,27 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sqrshrn_S(EmitterContext context) public static void Sqrshrn_S(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
} }
public static void Sqrshrn_V(EmitterContext context) public static void Sqrshrn_V(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
} }
public static void Sqrshrun_S(EmitterContext context) public static void Sqrshrun_S(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
} }
public static void Sqrshrun_V(EmitterContext context) public static void Sqrshrun_V(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
} }
public static void Sqshl_V(EmitterContext context) public static void Sqshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -265,9 +262,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)); Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -275,27 +270,27 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sqshrn_S(EmitterContext context) public static void Sqshrn_S(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
} }
public static void Sqshrn_V(EmitterContext context) public static void Sqshrn_V(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
} }
public static void Sqshrun_S(EmitterContext context) public static void Sqshrun_S(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
} }
public static void Sqshrun_V(EmitterContext context) public static void Sqshrun_V(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
} }
public static void Srshl_V(EmitterContext context) public static void Srshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -308,9 +303,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)); Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlReg), ne, me, Const(1), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -318,12 +311,12 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Srshr_S(EmitterContext context) public static void Srshr_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpSx(context, ShrImmFlags.Round); EmitScalarShrImmOpSx(context, ShrImmFlags.Round);
} }
public static void Srshr_V(EmitterContext context) public static void Srshr_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -363,12 +356,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Srsra_S(EmitterContext context) public static void Srsra_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); EmitScalarShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
} }
public static void Srsra_V(EmitterContext context) public static void Srsra_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -410,7 +403,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Sshl_V(EmitterContext context) public static void Sshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -423,9 +416,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)); Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlReg), ne, me, Const(0), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -433,7 +424,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Sshll_V(EmitterContext context) public static void Sshll_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -467,12 +458,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Sshr_S(EmitterContext context) public static void Sshr_S(ArmEmitterContext context)
{ {
EmitShrImmOp(context, ShrImmFlags.ScalarSx); EmitShrImmOp(context, ShrImmFlags.ScalarSx);
} }
public static void Sshr_V(EmitterContext context) public static void Sshr_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -499,12 +490,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ssra_S(EmitterContext context) public static void Ssra_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpSx(context, ShrImmFlags.Accumulate); EmitScalarShrImmOpSx(context, ShrImmFlags.Accumulate);
} }
public static void Ssra_V(EmitterContext context) public static void Ssra_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -536,7 +527,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Uqrshl_V(EmitterContext context) public static void Uqrshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -549,9 +540,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)); Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -559,17 +548,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Uqrshrn_S(EmitterContext context) public static void Uqrshrn_S(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
} }
public static void Uqrshrn_V(EmitterContext context) public static void Uqrshrn_V(ArmEmitterContext context)
{ {
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx); EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
} }
public static void Uqshl_V(EmitterContext context) public static void Uqshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -582,9 +571,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)); Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -592,17 +579,17 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Uqshrn_S(EmitterContext context) public static void Uqshrn_S(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
} }
public static void Uqshrn_V(EmitterContext context) public static void Uqshrn_V(ArmEmitterContext context)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
} }
public static void Urshl_V(EmitterContext context) public static void Urshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -615,9 +602,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)); Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlReg), ne, me, Const(1), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -625,12 +610,12 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Urshr_S(EmitterContext context) public static void Urshr_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpZx(context, ShrImmFlags.Round); EmitScalarShrImmOpZx(context, ShrImmFlags.Round);
} }
public static void Urshr_V(EmitterContext context) public static void Urshr_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -668,12 +653,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ursra_S(EmitterContext context) public static void Ursra_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); EmitScalarShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
} }
public static void Ursra_V(EmitterContext context) public static void Ursra_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -713,7 +698,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ushl_V(EmitterContext context) public static void Ushl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
@ -726,9 +711,7 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size); Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)); Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlReg), ne, me, Const(0), Const(op.Size));
Operand e = context.Call(info, ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
@ -736,7 +719,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
public static void Ushll_V(EmitterContext context) public static void Ushll_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -770,12 +753,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Ushr_S(EmitterContext context) public static void Ushr_S(ArmEmitterContext context)
{ {
EmitShrImmOp(context, ShrImmFlags.ScalarZx); EmitShrImmOp(context, ShrImmFlags.ScalarZx);
} }
public static void Ushr_V(EmitterContext context) public static void Ushr_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -802,12 +785,12 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Usra_S(EmitterContext context) public static void Usra_S(ArmEmitterContext context)
{ {
EmitScalarShrImmOpZx(context, ShrImmFlags.Accumulate); EmitScalarShrImmOpZx(context, ShrImmFlags.Accumulate);
} }
public static void Usra_V(EmitterContext context) public static void Usra_V(ArmEmitterContext context)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -855,27 +838,27 @@ namespace ARMeilleure.Instructions
VectorZx = 0 VectorZx = 0
} }
private static void EmitScalarShrImmOpSx(EmitterContext context, ShrImmFlags flags) private static void EmitScalarShrImmOpSx(ArmEmitterContext context, ShrImmFlags flags)
{ {
EmitShrImmOp(context, ShrImmFlags.ScalarSx | flags); EmitShrImmOp(context, ShrImmFlags.ScalarSx | flags);
} }
private static void EmitScalarShrImmOpZx(EmitterContext context, ShrImmFlags flags) private static void EmitScalarShrImmOpZx(ArmEmitterContext context, ShrImmFlags flags)
{ {
EmitShrImmOp(context, ShrImmFlags.ScalarZx | flags); EmitShrImmOp(context, ShrImmFlags.ScalarZx | flags);
} }
private static void EmitVectorShrImmOpSx(EmitterContext context, ShrImmFlags flags) private static void EmitVectorShrImmOpSx(ArmEmitterContext context, ShrImmFlags flags)
{ {
EmitShrImmOp(context, ShrImmFlags.VectorSx | flags); EmitShrImmOp(context, ShrImmFlags.VectorSx | flags);
} }
private static void EmitVectorShrImmOpZx(EmitterContext context, ShrImmFlags flags) private static void EmitVectorShrImmOpZx(ArmEmitterContext context, ShrImmFlags flags)
{ {
EmitShrImmOp(context, ShrImmFlags.VectorZx | flags); EmitShrImmOp(context, ShrImmFlags.VectorZx | flags);
} }
private static void EmitShrImmOp(EmitterContext context, ShrImmFlags flags) private static void EmitShrImmOp(ArmEmitterContext context, ShrImmFlags flags)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -925,7 +908,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static void EmitVectorShrImmNarrowOpZx(EmitterContext context, bool round) private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -974,12 +957,12 @@ namespace ARMeilleure.Instructions
VectorZxZx = 0 VectorZxZx = 0
} }
private static void EmitRoundShrImmSaturatingNarrowOp(EmitterContext context, ShrImmSaturatingNarrowFlags flags) private static void EmitRoundShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags)
{ {
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.Round | flags); EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.Round | flags);
} }
private static void EmitShrImmSaturatingNarrowOp(EmitterContext context, ShrImmSaturatingNarrowFlags flags) private static void EmitShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -1028,32 +1011,30 @@ namespace ARMeilleure.Instructions
// dst64 = (Int(src64, signed) + roundConst) >> shift; // dst64 = (Int(src64, signed) + roundConst) >> shift;
private static Operand EmitShrImm64( private static Operand EmitShrImm64(
EmitterContext context, ArmEmitterContext context,
Operand value, Operand value,
bool signed, bool signed,
long roundConst, long roundConst,
int shift) int shift)
{ {
string name = signed Delegate dlg = signed
? nameof(SoftFallback.SignedShrImm64) ? (Delegate)new _S64_S64_S64_S32(SoftFallback.SignedShrImm64)
: nameof(SoftFallback.UnsignedShrImm64); : (Delegate)new _U64_U64_S64_S32(SoftFallback.UnsignedShrImm64);
MethodInfo info = typeof(SoftFallback).GetMethod(name); return context.Call(dlg, value, Const(roundConst), Const(shift));
return context.Call(info, value, Const(roundConst), Const(shift));
} }
private static void EmitVectorShImmWidenBinarySx(EmitterContext context, Func2I emit, int imm) private static void EmitVectorShImmWidenBinarySx(ArmEmitterContext context, Func2I emit, int imm)
{ {
EmitVectorShImmWidenBinaryOp(context, emit, imm, signed: true); EmitVectorShImmWidenBinaryOp(context, emit, imm, signed: true);
} }
private static void EmitVectorShImmWidenBinaryZx(EmitterContext context, Func2I emit, int imm) private static void EmitVectorShImmWidenBinaryZx(ArmEmitterContext context, Func2I emit, int imm)
{ {
EmitVectorShImmWidenBinaryOp(context, emit, imm, signed: false); EmitVectorShImmWidenBinaryOp(context, emit, imm, signed: false);
} }
private static void EmitVectorShImmWidenBinaryOp(EmitterContext context, Func2I emit, int imm, bool signed) private static void EmitVectorShImmWidenBinaryOp(ArmEmitterContext context, Func2I emit, int imm, bool signed)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;

View file

@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
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.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -13,67 +12,63 @@ namespace ARMeilleure.Instructions
{ {
private const int DczSizeLog2 = 4; private const int DczSizeLog2 = 4;
public static void Hint(EmitterContext context) public static void Hint(ArmEmitterContext context)
{ {
//Execute as no-op. //Execute as no-op.
} }
public static void Isb(EmitterContext context) public static void Isb(ArmEmitterContext context)
{ {
//Execute as no-op. //Execute as no-op.
} }
public static void Mrs(EmitterContext context) public static void Mrs(ArmEmitterContext context)
{ {
OpCodeSystem op = (OpCodeSystem)context.CurrOp; OpCodeSystem op = (OpCodeSystem)context.CurrOp;
string name; Delegate dlg;
switch (GetPackedId(op)) switch (GetPackedId(op))
{ {
case 0b11_011_0000_0000_001: name = nameof(NativeInterface.GetCtrEl0); break; case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0); break;
case 0b11_011_0000_0000_111: name = nameof(NativeInterface.GetDczidEl0); break; case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0); break;
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.GetFpcr); break; case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr); break;
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.GetFpsr); break; case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr); break;
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.GetTpidrEl0); break; case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0); break;
case 0b11_011_1101_0000_011: name = nameof(NativeInterface.GetTpidr); break; case 0b11_011_1101_0000_011: dlg = new _U64(NativeInterface.GetTpidr); break;
case 0b11_011_1110_0000_000: name = nameof(NativeInterface.GetCntfrqEl0); break; case 0b11_011_1110_0000_000: dlg = new _U64(NativeInterface.GetCntfrqEl0); break;
case 0b11_011_1110_0000_001: name = nameof(NativeInterface.GetCntpctEl0); break; case 0b11_011_1110_0000_001: dlg = new _U64(NativeInterface.GetCntpctEl0); break;
default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
} }
MethodInfo info = typeof(NativeInterface).GetMethod(name); SetIntOrZR(context, op.Rt, context.Call(dlg));
SetIntOrZR(context, op.Rt, context.Call(info));
} }
public static void Msr(EmitterContext context) public static void Msr(ArmEmitterContext context)
{ {
OpCodeSystem op = (OpCodeSystem)context.CurrOp; OpCodeSystem op = (OpCodeSystem)context.CurrOp;
string name; Delegate dlg;
switch (GetPackedId(op)) switch (GetPackedId(op))
{ {
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.SetFpcr); break; case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr); break;
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.SetFpsr); break; case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr); break;
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.SetTpidrEl0); break; case 0b11_011_1101_0000_010: dlg = new _Void_U64(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}.");
} }
MethodInfo info = typeof(NativeInterface).GetMethod(name); context.Call(dlg, GetIntOrZR(context, op.Rt));
context.Call(info, GetIntOrZR(context, op.Rt));
} }
public static void Nop(EmitterContext context) public static void Nop(ArmEmitterContext context)
{ {
//Do nothing. //Do nothing.
} }
public static void Sys(EmitterContext context) public static void Sys(ArmEmitterContext context)
{ {
//This instruction is used to do some operations on the CPU like cache invalidation, //This instruction is used to do some operations on the CPU like cache invalidation,
//address translation and the like. //address translation and the like.
@ -87,13 +82,11 @@ namespace ARMeilleure.Instructions
//DC ZVA //DC ZVA
Operand t = GetIntOrZR(context, op.Rt); Operand t = GetIntOrZR(context, op.Rt);
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
for (long offset = 0; offset < (4 << DczSizeLog2); offset += 8) for (long offset = 0; offset < (4 << DczSizeLog2); offset += 8)
{ {
Operand address = context.Add(t, Const(offset)); Operand address = context.Add(t, Const(offset));
context.Call(info, address, Const(0L)); context.Call(new _Void_U64_U64(NativeInterface.WriteUInt64), address, Const(0L));
} }
break; break;

View file

@ -1,8 +1,6 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System.Collections.Concurrent; using System;
using Thread = System.Threading.Thread;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@ -28,21 +26,17 @@ namespace ARMeilleure.Instructions
} }
} }
private static ConcurrentDictionary<Thread, ThreadContext> _contexts; [ThreadStatic]
private static ThreadContext _context;
static NativeInterface()
{
_contexts = new ConcurrentDictionary<Thread, ThreadContext>();
}
public static void RegisterThread(ExecutionContext context, MemoryManager memory) public static void RegisterThread(ExecutionContext context, MemoryManager memory)
{ {
_contexts.TryAdd(Thread.CurrentThread, new ThreadContext(context, memory)); _context = new ThreadContext(context, memory);
} }
public static void UnregisterThread() public static void UnregisterThread()
{ {
_contexts.TryRemove(Thread.CurrentThread, out _); _context = null;
} }
public static void Break(ulong address, int imm) public static void Break(ulong address, int imm)
@ -52,6 +46,8 @@ namespace ARMeilleure.Instructions
public static void SupervisorCall(ulong address, int imm) public static void SupervisorCall(ulong address, int imm)
{ {
System.Span<byte> test = stackalloc byte[0x2000];
GetContext().OnSupervisorCall(address, imm); GetContext().OnSupervisorCall(address, imm);
} }
@ -147,65 +143,55 @@ namespace ARMeilleure.Instructions
#region "Read exclusive" #region "Read exclusive"
public static byte ReadByteExclusive(ulong address) public static byte ReadByteExclusive(ulong address)
{ {
ThreadContext context = GetCurrentContext(); byte value = _context.Memory.ReadByte((long)address);
byte value = context.Memory.ReadByte((long)address); _context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
_context.ExclusiveValueLow = value;
context.ExclusiveAddress = GetMaskedExclusiveAddress(address); _context.ExclusiveValueHigh = 0;
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value; return value;
} }
public static ushort ReadUInt16Exclusive(ulong address) public static ushort ReadUInt16Exclusive(ulong address)
{ {
ThreadContext context = GetCurrentContext(); ushort value = _context.Memory.ReadUInt16((long)address);
ushort value = context.Memory.ReadUInt16((long)address); _context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
_context.ExclusiveValueLow = value;
context.ExclusiveAddress = GetMaskedExclusiveAddress(address); _context.ExclusiveValueHigh = 0;
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value; return value;
} }
public static uint ReadUInt32Exclusive(ulong address) public static uint ReadUInt32Exclusive(ulong address)
{ {
ThreadContext context = GetCurrentContext(); uint value = _context.Memory.ReadUInt32((long)address);
uint value = context.Memory.ReadUInt32((long)address); _context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
_context.ExclusiveValueLow = value;
context.ExclusiveAddress = GetMaskedExclusiveAddress(address); _context.ExclusiveValueHigh = 0;
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value; return value;
} }
public static ulong ReadUInt64Exclusive(ulong address) public static ulong ReadUInt64Exclusive(ulong address)
{ {
ThreadContext context = GetCurrentContext(); ulong value = _context.Memory.ReadUInt64((long)address);
ulong value = context.Memory.ReadUInt64((long)address); _context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
_context.ExclusiveValueLow = value;
context.ExclusiveAddress = GetMaskedExclusiveAddress(address); _context.ExclusiveValueHigh = 0;
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value; return value;
} }
public static V128 ReadVector128Exclusive(ulong address) public static V128 ReadVector128Exclusive(ulong address)
{ {
ThreadContext context = GetCurrentContext(); V128 value = _context.Memory.AtomicLoadInt128((long)address);
V128 value = context.Memory.AtomicLoadInt128((long)address); _context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
_context.ExclusiveValueLow = value.GetUInt64(0);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address); _context.ExclusiveValueHigh = value.GetUInt64(1);
context.ExclusiveValueLow = value.GetUInt64(0);
context.ExclusiveValueHigh = value.GetUInt64(1);
return value; return value;
} }
@ -241,15 +227,13 @@ namespace ARMeilleure.Instructions
#region "Write exclusive" #region "Write exclusive"
public static int WriteByteExclusive(ulong address, byte value) public static int WriteByteExclusive(ulong address, byte value)
{ {
ThreadContext context = GetCurrentContext(); bool success = _context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success) if (success)
{ {
success = context.Memory.AtomicCompareExchangeByte( success = _context.Memory.AtomicCompareExchangeByte(
(long)address, (long)address,
(byte)context.ExclusiveValueLow, (byte)_context.ExclusiveValueLow,
(byte)value); (byte)value);
if (success) if (success)
@ -263,15 +247,13 @@ namespace ARMeilleure.Instructions
public static int WriteUInt16Exclusive(ulong address, ushort value) public static int WriteUInt16Exclusive(ulong address, ushort value)
{ {
ThreadContext context = GetCurrentContext(); bool success = _context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success) if (success)
{ {
success = context.Memory.AtomicCompareExchangeInt16( success = _context.Memory.AtomicCompareExchangeInt16(
(long)address, (long)address,
(short)context.ExclusiveValueLow, (short)_context.ExclusiveValueLow,
(short)value); (short)value);
if (success) if (success)
@ -285,15 +267,13 @@ namespace ARMeilleure.Instructions
public static int WriteUInt32Exclusive(ulong address, uint value) public static int WriteUInt32Exclusive(ulong address, uint value)
{ {
ThreadContext context = GetCurrentContext(); bool success = _context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success) if (success)
{ {
success = context.Memory.AtomicCompareExchangeInt32( success = _context.Memory.AtomicCompareExchangeInt32(
(long)address, (long)address,
(int)context.ExclusiveValueLow, (int)_context.ExclusiveValueLow,
(int)value); (int)value);
if (success) if (success)
@ -307,15 +287,13 @@ namespace ARMeilleure.Instructions
public static int WriteUInt64Exclusive(ulong address, ulong value) public static int WriteUInt64Exclusive(ulong address, ulong value)
{ {
ThreadContext context = GetCurrentContext(); bool success = _context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success) if (success)
{ {
success = context.Memory.AtomicCompareExchangeInt64( success = _context.Memory.AtomicCompareExchangeInt64(
(long)address, (long)address,
(long)context.ExclusiveValueLow, (long)_context.ExclusiveValueLow,
(long)value); (long)value);
if (success) if (success)
@ -329,15 +307,13 @@ namespace ARMeilleure.Instructions
public static int WriteVector128Exclusive(ulong address, V128 value) public static int WriteVector128Exclusive(ulong address, V128 value)
{ {
ThreadContext context = GetCurrentContext(); bool success = _context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success) if (success)
{ {
V128 expected = new V128(context.ExclusiveValueLow, context.ExclusiveValueHigh); V128 expected = new V128(_context.ExclusiveValueLow, _context.ExclusiveValueHigh);
success = context.Memory.AtomicCompareExchangeInt128((long)address, expected, value); success = _context.Memory.AtomicCompareExchangeInt128((long)address, expected, value);
if (success) if (success)
{ {
@ -356,7 +332,7 @@ namespace ARMeilleure.Instructions
public static void ClearExclusive() public static void ClearExclusive()
{ {
GetCurrentContext().ExclusiveAddress = ulong.MaxValue; _context.ExclusiveAddress = ulong.MaxValue;
} }
public static void CheckSynchronization() public static void CheckSynchronization()
@ -364,19 +340,14 @@ namespace ARMeilleure.Instructions
GetContext().CheckInterrupt(); GetContext().CheckInterrupt();
} }
private static ThreadContext GetCurrentContext()
{
return _contexts[Thread.CurrentThread];
}
public static ExecutionContext GetContext() public static ExecutionContext GetContext()
{ {
return _contexts[Thread.CurrentThread].Context; return _context.Context;
} }
public static MemoryManager GetMemoryManager() public static MemoryManager GetMemoryManager()
{ {
return _contexts[Thread.CurrentThread].Memory; return _context.Memory;
} }
} }
} }

View file

@ -41,6 +41,7 @@ namespace ARMeilleure.IntermediateRepresentation
Multiply64HighSI, Multiply64HighSI,
Multiply64HighUI, Multiply64HighUI,
Negate, Negate,
PopCount,
Return, Return,
RotateRight, RotateRight,
ShiftLeft, ShiftLeft,
@ -57,6 +58,7 @@ namespace ARMeilleure.IntermediateRepresentation
Store8, Store8,
StoreToContext, StoreToContext,
Subtract, Subtract,
VectorCreateScalar,
VectorExtract, VectorExtract,
VectorExtract16, VectorExtract16,
VectorExtract8, VectorExtract8,

View file

@ -237,7 +237,7 @@ namespace ARMeilleure.Memory
IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size)); IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size));
//Try to swap the current pointer (should be zero), with the allocated one. //Try to swap the current pointer (should be zero), with the allocated one.
nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr); nextPtr = Interlocked.CompareExchange(ref *ptePtr, newPtr, IntPtr.Zero);
//If the old pointer is not null, then another thread already has set it. //If the old pointer is not null, then another thread already has set it.
if (nextPtr != IntPtr.Zero) if (nextPtr != IntPtr.Zero)

View file

@ -112,19 +112,34 @@ namespace ARMeilleure.State
public static int GetRegisterOffset(Register reg) public static int GetRegisterOffset(Register reg)
{ {
int offset, size;
if (reg.Type == RegisterType.Integer) if (reg.Type == RegisterType.Integer)
{ {
return reg.Index * IntSize; offset = reg.Index * IntSize;
size = IntSize;
} }
else if (reg.Type == RegisterType.Vector) else if (reg.Type == RegisterType.Vector)
{ {
return RegisterConsts.IntRegsCount * IntSize + reg.Index * VecSize; offset = RegisterConsts.IntRegsCount * IntSize + reg.Index * VecSize;
size = VecSize;
} }
else /* if (reg.Type == RegisterType.Flag) */ else /* if (reg.Type == RegisterType.Flag) */
{ {
return RegisterConsts.IntRegsCount * IntSize + offset = RegisterConsts.IntRegsCount * IntSize +
RegisterConsts.VecRegsCount * VecSize + reg.Index * FlagSize; RegisterConsts.VecRegsCount * VecSize + reg.Index * FlagSize;
size = FlagSize;
} }
if ((uint)(offset + size) > (uint)TotalSize)
{
throw new ArgumentException("Invalid register.");
}
return offset;
} }
public static int GetCounterOffset() public static int GetCounterOffset()

View file

@ -0,0 +1,136 @@
using ARMeilleure.Decoders;
using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.State;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Translation
{
class ArmEmitterContext : EmitterContext
{
private OpCode _optOpLastCompare;
private OpCode _optOpLastFlagSet;
private Operand _optCmpTempN;
private Operand _optCmpTempM;
private Block _currBlock;
public Block CurrBlock
{
get
{
return _currBlock;
}
set
{
_currBlock = value;
ResetBlockState();
}
}
public OpCode CurrOp { get; set; }
public MemoryManager Memory { get; }
public Aarch32Mode Mode { get; }
public ArmEmitterContext(MemoryManager memory, Aarch32Mode mode)
{
Memory = memory;
Mode = mode;
}
public void MarkComparison(Operand n, Operand m)
{
_optOpLastCompare = CurrOp;
_optCmpTempN = Copy(n);
_optCmpTempM = Copy(m);
}
public void MarkFlagSet(PState stateFlag)
{
// Set this only if any of the NZCV flag bits were modified.
// This is used to ensure that when emiting a direct IL branch
// instruction for compare + branch sequences, we're not expecting
// to use comparison values from an old instruction, when in fact
// the flags were already overwritten by another instruction further along.
if (stateFlag >= PState.VFlag)
{
_optOpLastFlagSet = CurrOp;
}
}
private void ResetBlockState()
{
_optOpLastCompare = null;
_optOpLastFlagSet = null;
}
public Operand TryGetComparisonResult(Condition condition)
{
if (_optOpLastCompare == null || _optOpLastCompare != _optOpLastFlagSet)
{
return null;
}
Operand n = _optCmpTempN;
Operand m = _optCmpTempM;
InstName cmpName = _optOpLastCompare.Instruction.Name;
if (cmpName == InstName.Subs)
{
switch (condition)
{
case Condition.Eq: return ICompareEqual (n, m);
case Condition.Ne: return ICompareNotEqual (n, m);
case Condition.GeUn: return ICompareGreaterOrEqualUI(n, m);
case Condition.LtUn: return ICompareLessUI (n, m);
case Condition.GtUn: return ICompareGreaterUI (n, m);
case Condition.LeUn: return ICompareLessOrEqualUI (n, m);
case Condition.Ge: return ICompareGreaterOrEqual (n, m);
case Condition.Lt: return ICompareLess (n, m);
case Condition.Gt: return ICompareGreater (n, m);
case Condition.Le: return ICompareLessOrEqual (n, m);
}
}
else if (cmpName == InstName.Adds && _optOpLastCompare is IOpCodeAluImm op)
{
// There are several limitations that needs to be taken into account for CMN comparisons:
// - The unsigned comparisons are not valid, as they depend on the
// carry flag value, and they will have different values for addition and
// subtraction. For addition, it's carry, and for subtraction, it's borrow.
// So, we need to make sure we're not doing a unsigned compare for the CMN case.
// - We can only do the optimization for the immediate variants,
// because when the second operand value is exactly INT_MIN, we can't
// negate the value as theres no positive counterpart.
// Such invalid values can't be encoded on the immediate encodings.
if (op.RegisterSize == RegisterSize.Int32)
{
m = Const((int)-op.Immediate);
}
else
{
m = Const(-op.Immediate);
}
switch (condition)
{
case Condition.Eq: return ICompareEqual (n, m);
case Condition.Ne: return ICompareNotEqual (n, m);
case Condition.Ge: return ICompareGreaterOrEqual(n, m);
case Condition.Lt: return ICompareLess (n, m);
case Condition.Gt: return ICompareGreater (n, m);
case Condition.Le: return ICompareLessOrEqual (n, m);
}
}
return null;
}
}
}

View file

@ -11,12 +11,16 @@ namespace ARMeilleure.Translation
{ {
public static T Compile<T>(ControlFlowGraph cfg, OperandType funcReturnType) public static T Compile<T>(ControlFlowGraph cfg, OperandType funcReturnType)
{ {
IntPtr codePtr = JitCache.Map(Compile(cfg, funcReturnType)); CompilerContext cctx = GetCompilerContext(cfg, funcReturnType);
CompiledFunction func = CodeGenerator.Generate(cctx);
IntPtr codePtr = JitCache.Map(func);
return Marshal.GetDelegateForFunctionPointer<T>(codePtr); return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
} }
public static CompiledFunction Compile(ControlFlowGraph cfg, OperandType funcReturnType) private static CompilerContext GetCompilerContext(ControlFlowGraph cfg, OperandType funcReturnType)
{ {
Logger.StartPass(PassName.Dominance); Logger.StartPass(PassName.Dominance);
@ -31,9 +35,7 @@ namespace ARMeilleure.Translation
Logger.EndPass(PassName.SsaConstruction, cfg); Logger.EndPass(PassName.SsaConstruction, cfg);
CompilerContext cctx = new CompilerContext(cfg, funcReturnType); return new CompilerContext(cfg, funcReturnType);
return CodeGenerator.Generate(cctx);
} }
} }
} }

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Concurrent;
using System.Reflection;
namespace ARMeilleure.Translation
{
static class DelegateCache
{
private static ConcurrentDictionary<string, Delegate> _delegates;
static DelegateCache()
{
_delegates = new ConcurrentDictionary<string, Delegate>();
}
public static Delegate GetOrAdd(Delegate dlg)
{
return _delegates.GetOrAdd(GetKey(dlg.Method), (key) => dlg);
}
private static string GetKey(MethodInfo info)
{
return $"{info.DeclaringType.FullName}.{info.Name}";
}
}
}

View file

@ -1,11 +1,8 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -13,12 +10,7 @@ namespace ARMeilleure.Translation
{ {
class EmitterContext class EmitterContext
{ {
public Block CurrBlock { get; set; }
public OpCode CurrOp { get; set; }
public Aarch32Mode Mode { get; }
public MemoryManager Memory { get; set; }
private Dictionary<ulong, Operand> _labels; private Dictionary<ulong, Operand> _labels;
@ -92,28 +84,16 @@ namespace ARMeilleure.Translation
return Add(Instruction.ByteSwap, Local(op1.Type), op1); return Add(Instruction.ByteSwap, Local(op1.Type), op1);
} }
public Operand Call(MethodInfo info, params Operand[] callArgs) public Operand Call(Delegate func, params Operand[] callArgs)
{ {
RuntimeHelpers.PrepareMethod(info.MethodHandle); //Add the delegate to the cache to ensure it will not be garbage collected.
func = DelegateCache.GetOrAdd(func);
long methodPtr = info.MethodHandle.GetFunctionPointer().ToInt64(); IntPtr ptr = Marshal.GetFunctionPointerForDelegate(func);
Operand[] args = new Operand[callArgs.Length + 1]; OperandType returnType = GetOperandType(func.Method.ReturnType);
args[0] = Const(methodPtr); return Call(Const(ptr.ToInt64()), returnType, callArgs);
Array.Copy(callArgs, 0, args, 1, callArgs.Length);
if (info.ReturnType != typeof(void))
{
OperandType returnType = GetOperandType(info.ReturnType);
return Add(Instruction.Call, Local(returnType), args);
}
else
{
return Add(Instruction.Call, null, args);
}
} }
private static OperandType GetOperandType(Type type) private static OperandType GetOperandType(Type type)
@ -146,12 +126,30 @@ namespace ARMeilleure.Translation
return OperandType.V128; return OperandType.V128;
} }
if (type == typeof(void))
{
return OperandType.None;
}
throw new ArgumentException($"Invalid type \"{type.Name}\"."); throw new ArgumentException($"Invalid type \"{type.Name}\".");
} }
public Operand Call(OperandType returnType, params Operand[] callArgs) public Operand Call(Operand address, OperandType returnType, params Operand[] callArgs)
{ {
return Add(Instruction.Call, Local(returnType), callArgs); Operand[] args = new Operand[callArgs.Length + 1];
args[0] = address;
Array.Copy(callArgs, 0, args, 1, callArgs.Length);
if (returnType != OperandType.None)
{
return Add(Instruction.Call, Local(returnType), args);
}
else
{
return Add(Instruction.Call, null, args);
}
} }
public Operand CompareAndSwap128(Operand address, Operand expected, Operand desired) public Operand CompareAndSwap128(Operand address, Operand expected, Operand desired)
@ -186,6 +184,11 @@ namespace ARMeilleure.Translation
public Operand Copy(Operand dest, Operand op1) public Operand Copy(Operand dest, Operand op1)
{ {
if (dest.Kind != OperandKind.Register)
{
throw new ArgumentException($"Invalid dest operand kind \"{dest.Kind}\".");
}
return Add(Instruction.Copy, dest, op1); return Add(Instruction.Copy, dest, op1);
} }
@ -377,6 +380,11 @@ namespace ARMeilleure.Translation
return Add(Instruction.Subtract, Local(op1.Type), op1, op2); return Add(Instruction.Subtract, Local(op1.Type), op1, op2);
} }
public Operand VectorCreateScalar(Operand value)
{
return Add(Instruction.VectorCreateScalar, Local(OperandType.V128), value);
}
public Operand VectorExtract(OperandType type, Operand vector, int index) public Operand VectorExtract(OperandType type, Operand vector, int index)
{ {
return Add(Instruction.VectorExtract, Local(type), vector, Const(index)); return Add(Instruction.VectorExtract, Local(type), vector, Const(index));

View file

@ -2,6 +2,7 @@ using ARMeilleure.CodeGen;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
@ -10,7 +11,9 @@ namespace ARMeilleure.Translation
private const int PageSize = 4 * 1024; private const int PageSize = 4 * 1024;
private const int PageMask = PageSize - 1; private const int PageMask = PageSize - 1;
private static uint CacheSize = 512 * 1024 * 1024; private const int CodeAlignment = 4; // Bytes
private const int CacheSize = 512 * 1024 * 1024;
private static IntPtr _basePointer; private static IntPtr _basePointer;
@ -60,11 +63,13 @@ namespace ARMeilleure.Translation
private static int Allocate(int codeSize) private static int Allocate(int codeSize)
{ {
int allocOffset = _offset; codeSize = checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
_offset += codeSize; int newOffset = Interlocked.Add(ref _offset, codeSize);
if ((ulong)(uint)_offset > CacheSize) int allocOffset = newOffset - codeSize;
if ((ulong)(uint)newOffset > CacheSize)
{ {
throw new OutOfMemoryException(); throw new OutOfMemoryException();
} }
@ -75,10 +80,15 @@ namespace ARMeilleure.Translation
private static void Add(JitCacheEntry entry) private static void Add(JitCacheEntry entry)
{ {
//TODO: Use concurrent collection. //TODO: Use concurrent collection.
lock (_cacheEntries)
{
_cacheEntries.Add(entry); _cacheEntries.Add(entry);
} }
}
public static bool TryFind(int offset, out JitCacheEntry entry) public static bool TryFind(int offset, out JitCacheEntry entry)
{
lock (_cacheEntries)
{ {
foreach (JitCacheEntry cacheEntry in _cacheEntries) foreach (JitCacheEntry cacheEntry in _cacheEntries)
{ {
@ -91,6 +101,7 @@ namespace ARMeilleure.Translation
return true; return true;
} }
} }
}
entry = default(JitCacheEntry); entry = default(JitCacheEntry);

View file

@ -6,7 +6,6 @@ using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -38,11 +37,6 @@ namespace ARMeilleure.Translation
NativeInterface.UnregisterThread(); NativeInterface.UnregisterThread();
} }
public void SelfRegister(ExecutionContext context)
{
NativeInterface.RegisterThread(context, _memory);
}
public ulong ExecuteSingle(ExecutionContext context, ulong address) public ulong ExecuteSingle(ExecutionContext context, ulong address)
{ {
TranslatedFunction func = GetOrTranslate(address, ExecutionMode.Aarch64); TranslatedFunction func = GetOrTranslate(address, ExecutionMode.Aarch64);
@ -64,9 +58,7 @@ namespace ARMeilleure.Translation
private TranslatedFunction Translate(ulong address, ExecutionMode mode) private TranslatedFunction Translate(ulong address, ExecutionMode mode)
{ {
EmitterContext context = new EmitterContext(); ArmEmitterContext context = new ArmEmitterContext(_memory, Aarch32Mode.User);
context.Memory = _memory;
Logger.StartPass(PassName.Decoding); Logger.StartPass(PassName.Decoding);
@ -98,7 +90,7 @@ namespace ARMeilleure.Translation
return new TranslatedFunction(func); return new TranslatedFunction(func);
} }
private static ControlFlowGraph EmitAndGetCFG(EmitterContext context, Block[] blocks) private static ControlFlowGraph EmitAndGetCFG(ArmEmitterContext context, Block[] blocks)
{ {
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
{ {
@ -172,9 +164,7 @@ namespace ARMeilleure.Translation
context.BranchIfTrue(lblNonZero, count); context.BranchIfTrue(lblNonZero, count);
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)); context.Call(new _Void(NativeInterface.CheckSynchronization));
context.Call(info);
context.Branch(lblExit); context.Branch(lblExit);