Change placement of XMM callee save and restore code to match other compilers

This commit is contained in:
gdkchan 2019-07-28 00:22:28 -03:00
parent a3ea200444
commit db5e612914
4 changed files with 62 additions and 45 deletions

View file

@ -22,7 +22,7 @@ namespace ARMeilleure.CodeGen.X86
public BasicBlock CurrBlock { get; private set; }
public int CallArgsRegionSize { get; }
public int VecCalleeSaveSize { get; }
public int XmmSaveRegionSize { get; }
private long[] _blockOffsets;
@ -80,24 +80,24 @@ namespace ARMeilleure.CodeGen.X86
Assembler = new Assembler(stream);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int vecCalleeSaveSize);
VecCalleeSaveSize = vecCalleeSaveSize;
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
XmmSaveRegionSize = xmmSaveRegionSize;
_blockOffsets = new long[blocksCount];
_jumps = new List<Jump>();
}
private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int vecCalleeSaveSize)
private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize)
{
//We need to add 8 bytes to the total size, as the call to this
//function already pushed 8 bytes (the return address).
int intMask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters;
int vecMask = CallingConvention.GetVecCalleeSavedRegisters() & allocResult.VecUsedRegisters;
vecCalleeSaveSize = BitUtils.CountBits(vecMask) * 16;
xmmSaveRegionSize = BitUtils.CountBits(vecMask) * 16;
int calleeSaveRegionSize = BitUtils.CountBits(intMask) * 8 + vecCalleeSaveSize + 8;
int calleeSaveRegionSize = BitUtils.CountBits(intMask) * 8 + xmmSaveRegionSize + 8;
int argsCount = maxCallArgs;

View file

@ -1523,9 +1523,23 @@ namespace ARMeilleure.CodeGen.X86
mask &= ~(1 << bit);
}
mask = CallingConvention.GetVecCalleeSavedRegisters() & context.AllocResult.VecUsedRegisters;
int reservedStackSize = context.CallArgsRegionSize + context.AllocResult.SpillRegionSize;
int offset = 0;
reservedStackSize += context.XmmSaveRegionSize;
if (reservedStackSize >= StackGuardSize)
{
GenerateInlineStackProbe(context, reservedStackSize);
}
if (reservedStackSize != 0)
{
context.Assembler.Sub(rsp, new Operand(reservedStackSize), OperandType.I64);
}
int offset = reservedStackSize;
mask = CallingConvention.GetVecCalleeSavedRegisters() & context.AllocResult.VecUsedRegisters;
while (mask != 0)
{
@ -1542,20 +1556,6 @@ namespace ARMeilleure.CodeGen.X86
mask &= ~(1 << bit);
}
int reservedStackSize = context.CallArgsRegionSize + context.AllocResult.SpillRegionSize;
reservedStackSize += context.VecCalleeSaveSize;
if (reservedStackSize >= StackGuardSize)
{
GenerateInlineStackProbe(context, reservedStackSize);
}
if (reservedStackSize != 0)
{
context.Assembler.Sub(rsp, new Operand(reservedStackSize), OperandType.I64);
}
return new UnwindInfo(pushEntries.ToArray(), context.StreamOffset, reservedStackSize);
}
@ -1565,17 +1565,12 @@ namespace ARMeilleure.CodeGen.X86
int reservedStackSize = context.CallArgsRegionSize + context.AllocResult.SpillRegionSize;
reservedStackSize += context.VecCalleeSaveSize;
reservedStackSize += context.XmmSaveRegionSize;
if (reservedStackSize != 0)
{
context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
}
int offset = reservedStackSize;
int mask = CallingConvention.GetVecCalleeSavedRegisters() & context.AllocResult.VecUsedRegisters;
int offset = 0;
while (mask != 0)
{
int bit = BitUtils.LowestBitSet(mask);
@ -1589,6 +1584,11 @@ namespace ARMeilleure.CodeGen.X86
mask &= ~(1 << bit);
}
if (reservedStackSize != 0)
{
context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
}
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
while (mask != 0)

View file

@ -58,7 +58,7 @@ namespace ARMeilleure.Translation
{
// Map pages that are already full as RX.
// Map pages that are not full yet as RWX.
// On unix, the address and size must be page aligned.
// On unix, the address must be page aligned.
int endOffs = offset + size;
int pageStart = offset & ~PageMask;

View file

@ -99,31 +99,48 @@ namespace ARMeilleure.Translation
var unwindInfo = funcEntry.UnwindInfo;
_unwindInfo->UnwindCodes[0] = PackUwop(UnwindOperation.AllocLarge, unwindInfo.PrologueSize, 1);
_unwindInfo->UnwindCodes[1] = (ushort)(unwindInfo.FixedAllocSize >> 0);
_unwindInfo->UnwindCodes[2] = (ushort)(unwindInfo.FixedAllocSize >> 16);
int codeIndex = 0;
int codeIndex = 3;
int spOffset = unwindInfo.FixedAllocSize;
int spOffset = 0;
foreach (var entry in unwindInfo.PushEntries)
{
if (entry.Type == RegisterType.Vector)
{
spOffset -= 16;
}
}
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
{
var entry = unwindInfo.PushEntries[index];
bool isInteger = entry.Type == RegisterType.Integer;
UnwindOperation uwop = isInteger
? UnwindOperation.PushNonvol
: UnwindOperation.SaveXmm128;
_unwindInfo->UnwindCodes[codeIndex++] = PackUwop(uwop, entry.StreamEndOffset, entry.Index);
if (!isInteger)
if (entry.Type == RegisterType.Vector)
{
ushort uwop = PackUwop(UnwindOperation.SaveXmm128, entry.StreamEndOffset, entry.Index);
_unwindInfo->UnwindCodes[codeIndex++] = uwop;
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)spOffset;
spOffset -= 16;
spOffset += 16;
}
}
_unwindInfo->UnwindCodes[0] = PackUwop(UnwindOperation.AllocLarge, unwindInfo.PrologueSize, 1);
_unwindInfo->UnwindCodes[1] = (ushort)(unwindInfo.FixedAllocSize >> 0);
_unwindInfo->UnwindCodes[2] = (ushort)(unwindInfo.FixedAllocSize >> 16);
codeIndex += 3;
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
{
var entry = unwindInfo.PushEntries[index];
if (entry.Type == RegisterType.Integer)
{
ushort uwop = PackUwop(UnwindOperation.PushNonvol, entry.StreamEndOffset, entry.Index);
_unwindInfo->UnwindCodes[codeIndex++] = uwop;
}
}