ARMeilleure: replace else-ifs with switch statements #124

Closed
LukeWarnut wants to merge 1 commits from switch-st into master
20 changed files with 675 additions and 651 deletions
Showing only changes of commit ae82452179 - Show all commits

View File

@ -1445,17 +1445,16 @@ namespace ARMeilleure.CodeGen.Arm64
return false;
}
if (currentOp.Instruction == Instruction.Load)
switch (currentOp.Instruction)
{
context.Assembler.LdpRiUn(currentOp.Destination, nextOp.Destination, op1Base, op1Offset);
}
else if (currentOp.Instruction == Instruction.Store)
{
context.Assembler.StpRiUn(currentOp.GetSource(1), nextOp.GetSource(1), op1Base, op1Offset);
}
else
{
return false;
case Instruction.Load:
context.Assembler.LdpRiUn(currentOp.Destination, nextOp.Destination, op1Base, op1Offset);
break;
case Instruction.Store:
context.Assembler.StpRiUn(currentOp.GetSource(1), nextOp.GetSource(1), op1Base, op1Offset);
break;
default:
return false;
}
return true;

View File

@ -1099,17 +1099,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static int GetOperandId(Operand operand)
{
if (operand.Kind == OperandKind.LocalVariable)
switch (operand.Kind)
{
return operand.GetLocalNumber();
}
else if (operand.Kind == OperandKind.Register)
{
return GetRegisterId(operand.GetRegister());
}
else
{
throw new ArgumentException($"Invalid operand kind \"{operand.Kind}\".");
case OperandKind.LocalVariable:
return operand.GetLocalNumber();
case OperandKind.Register:
return GetRegisterId(operand.GetRegister());
default:
throw new ArgumentException($"Invalid operand kind \"{operand.Kind}\".");
}
}

View File

@ -33,17 +33,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int GetAvailableRegisters(RegisterType type)
{
if (type == RegisterType.Integer)
switch (type)
{
return IntAvailableRegisters;
}
else if (type == RegisterType.Vector)
{
return VecAvailableRegisters;
}
else
{
throw new ArgumentException($"Invalid register type \"{type}\".");
case RegisterType.Integer:
return IntAvailableRegisters;
case RegisterType.Vector:
return VecAvailableRegisters;
default:
throw new ArgumentException($"Invalid register type \"{type}\".");
}
}
}

View File

@ -754,73 +754,79 @@ namespace ARMeilleure.CodeGen.X86
if (source != default)
{
if (source.Kind == OperandKind.Constant)
switch (source.Kind)
{
ulong imm = source.Value;
case OperandKind.Constant:
ulong imm = source.Value;
if (inst == X86Instruction.Mov8)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else if (inst == X86Instruction.Mov16)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt16((short)imm);
}
else if (IsImm8(imm, type) && info.OpRMImm8 != BadOp)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else if (!source.Relocatable && IsImm32(imm, type) && info.OpRMImm32 != BadOp)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt32((int)imm);
}
else if (dest != default && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
{
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
if (rexPrefix != 0)
if (inst == X86Instruction.Mov8)
{
WriteByte((byte)rexPrefix);
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
if (HasRelocs && source.Relocatable)
else if (inst == X86Instruction.Mov16)
{
_relocs.Add(new Reloc
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt16((short)imm);
}
else if (IsImm8(imm, type) && info.OpRMImm8 != BadOp)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else if (!source.Relocatable && IsImm32(imm, type) && info.OpRMImm32 != BadOp)
{
WriteOpCode(dest, default, default, type, info.Flags, info.OpRMImm32);
WriteInt32((int)imm);
}
else if (dest != default && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
{
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
if (rexPrefix != 0)
{
JumpIndex = _jumps.Count - 1,
Position = (int)_stream.Position,
Symbol = source.Symbol,
});
WriteByte((byte)rexPrefix);
}
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
if (HasRelocs && source.Relocatable)
{
_relocs.Add(new Reloc
{
JumpIndex = _jumps.Count - 1,
Position = (int)_stream.Position,
Symbol = source.Symbol,
});
}
WriteUInt64(imm);
}
else
{
throw new ArgumentException($"Failed to encode constant 0x{imm:X}.");
}
WriteUInt64(imm);
}
else
{
throw new ArgumentException($"Failed to encode constant 0x{imm:X}.");
}
}
else if (source.Kind == OperandKind.Register && info.OpRMR != BadOp)
{
WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR);
}
else if (info.OpRRM != BadOp)
{
WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true);
}
else
{
throw new ArgumentException($"Invalid source operand kind \"{source.Kind}\".");
break;
case OperandKind.Register when info.OpRMR != BadOp:
WriteOpCode(dest, default, source, type, info.Flags, info.OpRMR);
break;
default:
if (info.OpRRM != BadOp)
{
WriteOpCode(dest, default, source, type, info.Flags, info.OpRRM, rrm: true);
}
else
{
throw new ArgumentException($"Invalid source operand kind \"{source.Kind}\".");
}
break;
}
}
else if (info.OpRRM != BadOp)
@ -848,32 +854,39 @@ namespace ARMeilleure.CodeGen.X86
if (src2 != default)
{
if (src2.Kind == OperandKind.Constant)
switch (src2.Kind)
{
ulong imm = src2.Value;
case OperandKind.Constant:
ulong imm = src2.Value;
if ((byte)imm == imm && info.OpRMImm8 != BadOp)
{
WriteOpCode(dest, src1, default, type, info.Flags, info.OpRMImm8);
if ((byte)imm == imm && info.OpRMImm8 != BadOp)
{
WriteOpCode(dest, src1, default, type, info.Flags, info.OpRMImm8);
WriteByte((byte)imm);
}
else
{
throw new ArgumentException($"Failed to encode constant 0x{imm:X}.");
}
}
else if (src2.Kind == OperandKind.Register && info.OpRMR != BadOp)
{
WriteOpCode(dest, src1, src2, type, info.Flags, info.OpRMR);
}
else if (info.OpRRM != BadOp)
{
WriteOpCode(dest, src1, src2, type, info.Flags, info.OpRRM, rrm: true);
}
else
{
throw new ArgumentException($"Invalid source operand kind \"{src2.Kind}\".");
WriteByte((byte)imm);
}
else
{
throw new ArgumentException($"Failed to encode constant 0x{imm:X}.");
}
break;
case OperandKind.Register when info.OpRMR != BadOp:
WriteOpCode(dest, src1, src2, type, info.Flags, info.OpRMR);
break;
default:
if (info.OpRRM != BadOp)
{
WriteOpCode(dest, src1, src2, type, info.Flags, info.OpRRM, rrm: true);
}
else
{
throw new ArgumentException($"Invalid source operand kind \"{src2.Kind}\".");
}
break;
}
}
else if (info.OpRRM != BadOp)
@ -913,49 +926,53 @@ namespace ARMeilleure.CodeGen.X86
if (dest != default)
{
if (dest.Kind == OperandKind.Register)
switch (dest.Kind)
{
int regIndex = dest.GetRegister().Index;
case OperandKind.Register:
int regIndex = dest.GetRegister().Index;
modRM |= (regIndex & 0b111) << (rrm ? 3 : 0);
modRM |= (regIndex & 0b111) << (rrm ? 3 : 0);
if ((flags & InstructionFlags.Reg8Dest) != 0 && regIndex >= 4)
{
rexPrefix |= RexPrefix;
}
}
else if (dest.Kind == OperandKind.Memory)
{
memOp = dest.GetMemory();
hasMemOp = true;
}
else
{
throw new ArgumentException("Invalid destination operand kind \"" + dest.Kind + "\".");
if ((flags & InstructionFlags.Reg8Dest) != 0 && regIndex >= 4)
{
rexPrefix |= RexPrefix;
}
break;
case OperandKind.Memory:
memOp = dest.GetMemory();
hasMemOp = true;
break;
default:
throw new ArgumentException("Invalid destination operand kind \"" + dest.Kind + "\".");
}
}
if (src2 != default)
{
if (src2.Kind == OperandKind.Register)
switch (src2.Kind)
{
int regIndex = src2.GetRegister().Index;
case OperandKind.Register:
int regIndex = src2.GetRegister().Index;
modRM |= (regIndex & 0b111) << (rrm ? 0 : 3);
modRM |= (regIndex & 0b111) << (rrm ? 0 : 3);
if ((flags & InstructionFlags.Reg8Src) != 0 && regIndex >= 4)
{
rexPrefix |= RexPrefix;
}
}
else if (src2.Kind == OperandKind.Memory && !hasMemOp)
{
memOp = src2.GetMemory();
hasMemOp = true;
}
else
{
throw new ArgumentException("Invalid source operand kind \"" + src2.Kind + "\".");
if ((flags & InstructionFlags.Reg8Src) != 0 && regIndex >= 4)
{
rexPrefix |= RexPrefix;
}
break;
case OperandKind.Memory when !hasMemOp:
memOp = src2.GetMemory();
hasMemOp = true;
break;
default:
throw new ArgumentException("Invalid source operand kind \"" + src2.Kind + "\".");
}
}

View File

@ -423,25 +423,24 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(!dest.Type.IsInteger());
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
switch (info.Inst)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvpd, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Blendvps && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvps, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Pblendvb && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vpblendvb, dest, src1, src2, src3);
}
else
{
EnsureSameReg(dest, src1);
case X86Instruction.Blendvpd when HardwareCapabilities.SupportsVexEncoding:
context.Assembler.WriteInstruction(X86Instruction.Vblendvpd, dest, src1, src2, src3);
break;
case X86Instruction.Blendvps when HardwareCapabilities.SupportsVexEncoding:
context.Assembler.WriteInstruction(X86Instruction.Vblendvps, dest, src1, src2, src3);
break;
case X86Instruction.Pblendvb when HardwareCapabilities.SupportsVexEncoding:
context.Assembler.WriteInstruction(X86Instruction.Vpblendvb, dest, src1, src2, src3);
break;
default:
EnsureSameReg(dest, src1);
Debug.Assert(src3.GetRegister().Index == 0);
Debug.Assert(src3.GetRegister().Index == 0);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
break;
}
break;
@ -1406,88 +1405,91 @@ namespace ARMeilleure.CodeGen.X86
}
}
if (src2.Type == OperandType.I32)
switch (src2.Type)
{
Debug.Assert(index < 4);
case OperandType.I32:
Debug.Assert(index < 4);
if (HardwareCapabilities.SupportsSse41)
{
context.Assembler.Pinsrd(dest, src1, src2, index);
}
else
{
InsertIntSse2(2);
}
}
else if (src2.Type == OperandType.I64)
{
Debug.Assert(index < 2);
if (HardwareCapabilities.SupportsSse41)
{
context.Assembler.Pinsrq(dest, src1, src2, index);
}
else
{
InsertIntSse2(4);
}
}
else if (src2.Type == OperandType.FP32)
{
Debug.Assert(index < 4);
if (index != 0)
{
if (HardwareCapabilities.SupportsSse41)
{
context.Assembler.Insertps(dest, src1, src2, (byte)(index << 4));
context.Assembler.Pinsrd(dest, src1, src2, index);
}
else
{
if (src1.GetRegister() == src2.GetRegister())
InsertIntSse2(2);
}
break;
case OperandType.I64:
Debug.Assert(index < 2);
if (HardwareCapabilities.SupportsSse41)
{
context.Assembler.Pinsrq(dest, src1, src2, index);
}
else
{
InsertIntSse2(4);
}
break;
case OperandType.FP32:
{
Debug.Assert(index < 4);
if (index != 0)
{
int mask = 0b11_10_01_00;
if (HardwareCapabilities.SupportsSse41)
{
context.Assembler.Insertps(dest, src1, src2, (byte)(index << 4));
}
else
{
if (src1.GetRegister() == src2.GetRegister())
{
int mask = 0b11_10_01_00;
mask &= ~(0b11 << index * 2);
mask &= ~(0b11 << index * 2);
context.Assembler.Pshufd(dest, src1, (byte)mask);
context.Assembler.Pshufd(dest, src1, (byte)mask);
}
else
{
int mask0 = 0b11_10_01_00;
int mask1 = 0b11_10_01_00;
mask0 = BitUtils.RotateRight(mask0, index * 2, 8);
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
context.Assembler.Pshufd(src1, src1, (byte)mask0); // Lane to be inserted in position 0.
context.Assembler.Movss(dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0]
context.Assembler.Pshufd(dest, dest, (byte)mask1); // Inserted lane in original position.
if (dest.GetRegister() != src1.GetRegister())
{
context.Assembler.Pshufd(src1, src1, (byte)mask1); // Restore src1.
}
}
}
}
else
{
int mask0 = 0b11_10_01_00;
int mask1 = 0b11_10_01_00;
mask0 = BitUtils.RotateRight(mask0, index * 2, 8);
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
context.Assembler.Pshufd(src1, src1, (byte)mask0); // Lane to be inserted in position 0.
context.Assembler.Movss(dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0]
context.Assembler.Pshufd(dest, dest, (byte)mask1); // Inserted lane in original position.
if (dest.GetRegister() != src1.GetRegister())
{
context.Assembler.Pshufd(src1, src1, (byte)mask1); // Restore src1.
}
context.Assembler.Movss(dest, src1, src2);
}
}
}
else
{
context.Assembler.Movss(dest, src1, src2);
}
}
else /* if (src2.Type == OperandType.FP64) */
{
Debug.Assert(index < 2);
if (index != 0)
{
context.Assembler.Movlhps(dest, src1, src2);
}
else
{
context.Assembler.Movsd(dest, src1, src2);
}
break;
}
default:
Debug.Assert(index < 2);
if (index != 0)
{
context.Assembler.Movlhps(dest, src1, src2);
}
else
{
context.Assembler.Movsd(dest, src1, src2);
}
break;
}
}

View File

@ -141,19 +141,18 @@ namespace ARMeilleure.CodeGen.X86
Operand constOp;
Operand otherOp;
if (src1.Kind == OperandKind.Constant && src2.Kind == OperandKind.LocalVariable)
switch (src1.Kind)
{
constOp = src1;
otherOp = src2;
}
else if (src1.Kind == OperandKind.LocalVariable && src2.Kind == OperandKind.Constant)
{
constOp = src2;
otherOp = src1;
}
else
{
return 0;
case OperandKind.Constant when src2.Kind == OperandKind.LocalVariable:
constOp = src1;
otherOp = src2;
break;
case OperandKind.LocalVariable when src2.Kind == OperandKind.Constant:
constOp = src2;
otherOp = src1;
break;
default:
return 0;
}
// If we have addition by 64-bits constant, then we can't optimize it further,

View File

@ -10,30 +10,31 @@ namespace ARMeilleure.Decoders
public OpCodeAluImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
if (DataOp == DataOp.Arithmetic)
switch (DataOp)
{
Immediate = (opCode >> 10) & 0xfff;
case DataOp.Arithmetic:
Immediate = opCode >> 10 & 0xfff;
int shift = (opCode >> 22) & 3;
int shift = opCode >> 22 & 3;
Immediate <<= shift * 12;
}
else if (DataOp == DataOp.Logical)
{
var bm = DecoderHelper.DecodeBitMask(opCode, true);
Immediate <<= shift * 12;
break;
if (bm.IsUndefined)
{
Instruction = InstDescriptor.Undefined;
case DataOp.Logical:
var bm = DecoderHelper.DecodeBitMask(opCode, true);
return;
}
if (bm.IsUndefined)
{
Instruction = InstDescriptor.Undefined;
Immediate = bm.WMask;
}
else
{
throw new ArgumentException($"Invalid data operation: {DataOp}", nameof(opCode));
return;
}
Immediate = bm.WMask;
break;
default:
throw new ArgumentException($"Invalid data operation: {DataOp}", nameof(opCode));
}
}
}

View File

@ -1438,27 +1438,28 @@ namespace ARMeilleure.Decoders
// but 00 isn't.
char chr = encoding[index];
if (chr == '1')
switch (chr)
{
value |= 1 << bit;
}
else if (chr == 'x')
{
xMask |= 1 << bit;
}
else if (chr == '>')
{
xPos[xBits++] = bit;
}
else if (chr == '<')
{
xPos[xBits++] = bit;
case '1':
value |= 1 << bit;
break;
case 'x':
xMask |= 1 << bit;
break;
case '>':
xPos[xBits++] = bit;
break;
case '<':
xPos[xBits++] = bit;
blacklisted |= 1 << bit;
break;
default:
if (chr != '0')
{
throw new ArgumentException($"Invalid encoding: {encoding}", nameof(encoding));
}
blacklisted |= 1 << bit;
}
else if (chr != '0')
{
throw new ArgumentException($"Invalid encoding: {encoding}", nameof(encoding));
break;
}
}

View File

@ -1214,17 +1214,17 @@ namespace ARMeilleure.Instructions
elementAction(tempD, nByte, mByte);
if (b == 0)
switch (b)
{
result = context.ZeroExtend8(OperandType.I32, tempD);
}
else if (b < 3)
{
result = context.BitwiseOr(result, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, tempD), Const(b * 8)));
}
else
{
result = context.BitwiseOr(result, context.ShiftLeft(tempD, Const(24)));
case 0:
result = context.ZeroExtend8(OperandType.I32, tempD);
break;
case < 3:
result = context.BitwiseOr(result, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, tempD), Const(b * 8)));
break;
default:
result = context.BitwiseOr(result, context.ShiftLeft(tempD, Const(24)));
break;
}
}

View File

@ -69,32 +69,37 @@ namespace ARMeilleure.Instructions
// read all the data at once. For a 32-bits pairwise load, we do a
// simple 64-bits load, for a 128-bits load, we need to call a special
// method to read 128-bits atomically.
if (op.Size == 2)
switch (op.Size)
{
Operand value = EmitLoadExclusive(context, address, exclusive, 3);
case 2:
{
Operand value = EmitLoadExclusive(context, address, exclusive, 3);
Operand valueLow = context.ConvertI64ToI32(value);
Operand valueLow = context.ConvertI64ToI32(value);
valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
Operand valueHigh = context.ShiftRightUI(value, Const(32));
Operand valueHigh = context.ShiftRightUI(value, Const(32));
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
}
else if (op.Size == 3)
{
Operand value = EmitLoadExclusive(context, address, exclusive, 4);
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
break;
}
Operand valueLow = context.VectorExtract(OperandType.I64, value, 0);
Operand valueHigh = context.VectorExtract(OperandType.I64, value, 1);
case 3:
{
Operand value = EmitLoadExclusive(context, address, exclusive, 4);
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
}
else
{
throw new InvalidOperationException($"Invalid load size of {1 << op.Size} bytes.");
Operand valueLow = context.VectorExtract(OperandType.I64, value, 0);
Operand valueHigh = context.VectorExtract(OperandType.I64, value, 1);
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
break;
}
default:
throw new InvalidOperationException($"Invalid load size of {1 << op.Size} bytes.");
}
}
else

View File

@ -338,17 +338,17 @@ namespace ARMeilleure.Instructions
value = context.ConvertI64ToI32(value);
}
if (size == 0)
switch (size)
{
context.Store8(physAddr, value);
}
else if (size == 1)
{
context.Store16(physAddr, value);
}
else
{
context.Store(physAddr, value);
case 0:
context.Store8(physAddr, value);
break;
case 1:
context.Store16(physAddr, value);
break;
default:
context.Store(physAddr, value);
break;
}
}

View File

@ -100,40 +100,48 @@ namespace ARMeilleure.Instructions
{
Operand res = GetVec(op.Rn);
if (op.Size == 0)
switch (op.Size)
{
if (op.DstIndex != 0)
{
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(op.DstIndex));
}
case 0:
if (op.DstIndex != 0)
{
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(op.DstIndex));
}
res = context.AddIntrinsic(Intrinsic.X86Punpcklbw, res, res);
res = context.AddIntrinsic(Intrinsic.X86Punpcklwd, res, res);
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(0));
}
else if (op.Size == 1)
{
if (op.DstIndex != 0)
{
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(op.DstIndex * 2));
}
res = context.AddIntrinsic(Intrinsic.X86Punpcklbw, res, res);
res = context.AddIntrinsic(Intrinsic.X86Punpcklwd, res, res);
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(0));
break;
res = context.AddIntrinsic(Intrinsic.X86Punpcklwd, res, res);
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(0));
}
else if (op.Size == 2)
{
int mask = op.DstIndex * 0b01010101;
case 1:
if (op.DstIndex != 0)
{
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(op.DstIndex * 2));
}
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(mask));
}
else if (op.DstIndex == 0 && op.RegisterSize != RegisterSize.Simd64)
{
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, res);
}
else if (op.DstIndex == 1)
{
res = context.AddIntrinsic(Intrinsic.X86Movhlps, res, res);
res = context.AddIntrinsic(Intrinsic.X86Punpcklwd, res, res);
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(0));
break;
case 2:
{
int mask = op.DstIndex * 0b01010101;
res = context.AddIntrinsic(Intrinsic.X86Shufps, res, res, Const(mask));
break;
}
default:
if (op.DstIndex == 0 && op.RegisterSize != RegisterSize.Simd64)
{
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, res);
}
else if (op.DstIndex == 1)
{
res = context.AddIntrinsic(Intrinsic.X86Movhlps, res, res);
}
break;
}
if (op.RegisterSize == RegisterSize.Simd64)

View File

@ -221,54 +221,60 @@ namespace ARMeilleure.Instructions
if (op.U)
{
if (op.Size < 2)
switch (op.Size)
{
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
case < 2:
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightUI(op1, Const(shift));
}, accumulate);
}
else if (op.Size == 2)
{
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.ZeroExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightUI(op1, Const(shift));
}, accumulate);
break;
return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift)));
}, accumulate);
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift), accumulate);
case 2:
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.ZeroExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift)));
}, accumulate);
break;
default: // case 3
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift), accumulate);
break;
}
}
}
else
{
if (op.Size < 2)
switch (op.Size)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
case < 2:
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightSI(op1, Const(shift));
}, accumulate);
}
else if (op.Size == 2)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.SignExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightSI(op1, Const(shift));
}, accumulate);
break;
return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift)));
}, accumulate);
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift), accumulate);
case 2:
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.SignExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift)));
}, accumulate);
break;
default: // case 3
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift), accumulate);
break;
}
}
}

View File

@ -495,33 +495,33 @@ namespace ARMeilleure.Instructions
double result;
if (type == FPType.SNaN || type == FPType.QNaN)
switch (type)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat64.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
case FPType.SNaN:
case FPType.QNaN:
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat64.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat64.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat64.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
break;
case FPType.Infinity:
result = SoftFloat64.FPInfinity(sign);
break;
case FPType.Zero:
result = SoftFloat64.FPZero(sign);
break;
default:
result = FPRoundCv(real, context);
break;
}
return result;
@ -672,46 +672,49 @@ namespace ARMeilleure.Instructions
ushort resultBits;
if (type == FPType.SNaN || type == FPType.QNaN)
switch (type)
{
if (altHp)
{
case FPType.SNaN:
case FPType.QNaN:
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
break;
case FPType.Infinity:
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
break;
case FPType.Zero:
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
break;
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
default:
resultBits = SoftFloat16.FPRoundCv(real, context);
break;
}
return resultBits;
@ -1056,46 +1059,46 @@ namespace ARMeilleure.Instructions
{
if (value1 > value2)
{
if (type1 == FPType.Infinity)
switch (type1)
{
result = FPInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FPZero(sign1 && sign2);
}
else
{
result = value1;
case FPType.Infinity:
result = FPInfinity(sign1);
break;
case FPType.Zero:
result = FPZero(sign1 && sign2);
break;
default:
result = value1;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
result = FPZero(result < 0f);
}
result = FPZero(result < 0f);
}
break;
}
}
else
{
if (type2 == FPType.Infinity)
switch (type2)
{
result = FPInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FPZero(sign1 && sign2);
}
else
{
result = value2;
case FPType.Infinity:
result = FPInfinity(sign2);
break;
case FPType.Zero:
result = FPZero(sign1 && sign2);
break;
default:
result = value2;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
result = FPZero(result < 0f);
}
result = FPZero(result < 0f);
}
break;
}
}
}
@ -1147,46 +1150,46 @@ namespace ARMeilleure.Instructions
{
if (value1 < value2)
{
if (type1 == FPType.Infinity)
switch (type1)
{
result = FPInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FPZero(sign1 || sign2);
}
else
{
result = value1;
case FPType.Infinity:
result = FPInfinity(sign1);
break;
case FPType.Zero:
result = FPZero(sign1 || sign2);
break;
default:
result = value1;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
result = FPZero(result < 0f);
}
result = FPZero(result < 0f);
}
break;
}
}
else
{
if (type2 == FPType.Infinity)
switch (type2)
{
result = FPInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FPZero(sign1 || sign2);
}
else
{
result = value2;
case FPType.Infinity:
result = FPInfinity(sign2);
break;
case FPType.Zero:
result = FPZero(sign1 || sign2);
break;
default:
result = value2;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{
context.Fpsr |= FPSR.Ufc;
result = FPZero(result < 0f);
}
result = FPZero(result < 0f);
}
break;
}
}
}

View File

@ -184,41 +184,36 @@ namespace ARMeilleure.State
public unsafe static int GetRegisterOffset(Register reg)
{
if (reg.Type == RegisterType.Integer)
switch (reg.Type)
{
if ((uint)reg.Index >= RegisterConsts.IntRegsCount)
{
throw new ArgumentException("Invalid register.");
}
case RegisterType.Integer:
if ((uint)reg.Index >= RegisterConsts.IntRegsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[reg.Index]);
}
else if (reg.Type == RegisterType.Vector)
{
if ((uint)reg.Index >= RegisterConsts.VecRegsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[reg.Index]);
case RegisterType.Vector:
if ((uint)reg.Index >= RegisterConsts.VecRegsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.V[reg.Index * 2]);
}
else if (reg.Type == RegisterType.Flag)
{
if ((uint)reg.Index >= RegisterConsts.FlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.V[reg.Index * 2]);
case RegisterType.Flag:
if ((uint)reg.Index >= RegisterConsts.FlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Flags[reg.Index]);
}
else /* if (reg.Type == RegisterType.FpFlag) */
{
if ((uint)reg.Index >= RegisterConsts.FpFlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Flags[reg.Index]);
default: // case RegisterType.FpFlag
if ((uint)reg.Index >= RegisterConsts.FpFlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.FpFlags[reg.Index]);
return StorageOffset(ref _dummyStorage, ref _dummyStorage.FpFlags[reg.Index]);
}
}

View File

@ -137,20 +137,20 @@ namespace ARMeilleure.Translation.Cache
Debug.Assert(allocSize % 8 == 0);
if (allocSize <= 128)
switch (allocSize)
{
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
}
else if (allocSize <= 0x7FFF8)
{
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
}
else
{
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
case <= 128:
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
break;
case <= 0x7FFF8:
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
break;
default:
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
break;
}
break;

View File

@ -108,36 +108,36 @@ namespace ARMeilleure.Translation
protected static OperandType GetOperandType(Type type)
{
if (type == typeof(bool) || type == typeof(byte) ||
type == typeof(char) || type == typeof(short) ||
type == typeof(int) || type == typeof(sbyte) ||
type == typeof(ushort) || type == typeof(uint))
switch (Type.GetTypeCode(type))
{
return OperandType.I32;
}
else if (type == typeof(long) || type == typeof(ulong))
{
return OperandType.I64;
}
else if (type == typeof(double))
{
return OperandType.FP64;
}
else if (type == typeof(float))
{
return OperandType.FP32;
}
else if (type == typeof(V128))
{
return OperandType.V128;
}
else if (type == typeof(void))
{
return OperandType.None;
}
else
{
throw new ArgumentException($"Invalid type \"{type.Name}\".");
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
return OperandType.I32;
case TypeCode.Int64:
case TypeCode.UInt64:
return OperandType.I64;
case TypeCode.Double:
return OperandType.FP64;
case TypeCode.Single:
return OperandType.FP32;
case TypeCode.Object when type == typeof(V128):
return OperandType.V128;
case TypeCode.Object when type == typeof(void):
return OperandType.None;
default:
throw new ArgumentException($"Invalid type \"{type.Name}\".");
}
}

View File

@ -152,17 +152,16 @@ namespace ARMeilleure.Translation
while (node != null)
{
int cmp = key.CompareTo(node.Start);
if (cmp < 0)
switch (cmp)
{
node = node.Left;
}
else if (cmp > 0)
{
node = node.Right;
}
else
{
return node;
case < 0:
node = node.Left;
break;
case > 0:
node = node.Right;
break;
default:
return node;
}
}
return null;
@ -272,43 +271,42 @@ namespace ARMeilleure.Translation
{
parent = node;
int cmp = start.CompareTo(node.Start);
if (cmp < 0)
switch (cmp)
{
node = node.Left;
}
else if (cmp > 0)
{
node = node.Right;
}
else
{
outNode = node;
case < 0:
node = node.Left;
break;
case > 0:
node = node.Right;
break;
default:
outNode = node;
if (updateFactoryCallback != null)
{
// Replace
node.Value = updateFactoryCallback(start, node.Value);
int endCmp = end.CompareTo(node.End);
if (endCmp > 0)
if (updateFactoryCallback != null)
{
node.End = end;
if (end.CompareTo(node.Max) > 0)
// Replace
node.Value = updateFactoryCallback(start, node.Value);
int endCmp = end.CompareTo(node.End);
if (endCmp > 0)
{
node.Max = end;
PropagateIncrease(node);
RestoreBalanceAfterInsertion(node);
node.End = end;
if (end.CompareTo(node.Max) > 0)
{
node.Max = end;
PropagateIncrease(node);
RestoreBalanceAfterInsertion(node);
}
}
else if (endCmp < 0)
{
node.End = end;
PropagateFull(node);
}
}
else if (endCmp < 0)
{
node.End = end;
PropagateFull(node);
}
}
return false;
return false;
}
}
IntervalTreeNode<TK, TV> newNode = new(start, end, value, parent);

View File

@ -977,27 +977,24 @@ namespace ARMeilleure.Translation.PTC
private static FeatureInfo GetFeatureInfo()
{
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
switch (RuntimeInformation.ProcessArchitecture)
{
return new FeatureInfo(
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap,
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap2,
(ulong)Arm64HardwareCapabilities.MacOsFeatureInfo,
0,
0);
}
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
return new FeatureInfo(
(ulong)X86HardwareCapabilities.FeatureInfo1Ecx,
(ulong)X86HardwareCapabilities.FeatureInfo1Edx,
(ulong)X86HardwareCapabilities.FeatureInfo7Ebx,
(ulong)X86HardwareCapabilities.FeatureInfo7Ecx,
(ulong)X86HardwareCapabilities.Xcr0InfoEax);
}
else
{
return new FeatureInfo(0, 0, 0, 0, 0);
case Architecture.Arm64:
return new FeatureInfo(
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap,
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap2,
(ulong)Arm64HardwareCapabilities.MacOsFeatureInfo,
0,
0);
case Architecture.X64:
return new FeatureInfo(
(ulong)X86HardwareCapabilities.FeatureInfo1Ecx,
(ulong)X86HardwareCapabilities.FeatureInfo1Edx,
(ulong)X86HardwareCapabilities.FeatureInfo7Ebx,
(ulong)X86HardwareCapabilities.FeatureInfo7Ecx,
(ulong)X86HardwareCapabilities.Xcr0InfoEax);
default:
return new FeatureInfo(0, 0, 0, 0, 0);
}
}

View File

@ -244,21 +244,20 @@ namespace ARMeilleure.Translation
{
Register reg = operand.GetRegister();
if (reg.Type == RegisterType.Integer)
switch (reg.Type)
{
result = reg.Index;
}
else if (reg.Type == RegisterType.Vector)
{
result = RegisterConsts.IntRegsCount + reg.Index;
}
else if (reg.Type == RegisterType.Flag)
{
result = RegisterConsts.IntAndVecRegsCount + reg.Index;
}
else /* if (reg.Type == RegisterType.FpFlag) */
{
result = RegisterConsts.FpFlagsOffset + reg.Index;
case RegisterType.Integer:
result = reg.Index;
break;
case RegisterType.Vector:
result = RegisterConsts.IntRegsCount + reg.Index;
break;
case RegisterType.Flag:
result = RegisterConsts.IntAndVecRegsCount + reg.Index;
break;
default: // case RegisterType.FpFlag
result = RegisterConsts.FpFlagsOffset + reg.Index;
break;
}
return true;