Change placement of XMM callee save and restore code to match other compilers
This commit is contained in:
parent
a3ea200444
commit
db5e612914
4 changed files with 62 additions and 45 deletions
|
@ -22,7 +22,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
public BasicBlock CurrBlock { get; private set; }
|
public BasicBlock CurrBlock { get; private set; }
|
||||||
|
|
||||||
public int CallArgsRegionSize { get; }
|
public int CallArgsRegionSize { get; }
|
||||||
public int VecCalleeSaveSize { get; }
|
public int XmmSaveRegionSize { get; }
|
||||||
|
|
||||||
private long[] _blockOffsets;
|
private long[] _blockOffsets;
|
||||||
|
|
||||||
|
@ -80,24 +80,24 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Assembler = new Assembler(stream);
|
Assembler = new Assembler(stream);
|
||||||
|
|
||||||
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int vecCalleeSaveSize);
|
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
|
||||||
VecCalleeSaveSize = vecCalleeSaveSize;
|
XmmSaveRegionSize = xmmSaveRegionSize;
|
||||||
|
|
||||||
_blockOffsets = new long[blocksCount];
|
_blockOffsets = new long[blocksCount];
|
||||||
|
|
||||||
_jumps = new List<Jump>();
|
_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
|
//We need to add 8 bytes to the total size, as the call to this
|
||||||
//function already pushed 8 bytes (the return address).
|
//function already pushed 8 bytes (the return address).
|
||||||
int intMask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters;
|
int intMask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters;
|
||||||
int vecMask = CallingConvention.GetVecCalleeSavedRegisters() & allocResult.VecUsedRegisters;
|
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;
|
int argsCount = maxCallArgs;
|
||||||
|
|
||||||
|
|
|
@ -1523,9 +1523,23 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
mask &= ~(1 << bit);
|
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)
|
while (mask != 0)
|
||||||
{
|
{
|
||||||
|
@ -1542,20 +1556,6 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
mask &= ~(1 << bit);
|
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);
|
return new UnwindInfo(pushEntries.ToArray(), context.StreamOffset, reservedStackSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1565,17 +1565,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
int reservedStackSize = context.CallArgsRegionSize + context.AllocResult.SpillRegionSize;
|
int reservedStackSize = context.CallArgsRegionSize + context.AllocResult.SpillRegionSize;
|
||||||
|
|
||||||
reservedStackSize += context.VecCalleeSaveSize;
|
reservedStackSize += context.XmmSaveRegionSize;
|
||||||
|
|
||||||
if (reservedStackSize != 0)
|
int offset = reservedStackSize;
|
||||||
{
|
|
||||||
context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mask = CallingConvention.GetVecCalleeSavedRegisters() & context.AllocResult.VecUsedRegisters;
|
int mask = CallingConvention.GetVecCalleeSavedRegisters() & context.AllocResult.VecUsedRegisters;
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
while (mask != 0)
|
while (mask != 0)
|
||||||
{
|
{
|
||||||
int bit = BitUtils.LowestBitSet(mask);
|
int bit = BitUtils.LowestBitSet(mask);
|
||||||
|
@ -1589,6 +1584,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
mask &= ~(1 << bit);
|
mask &= ~(1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reservedStackSize != 0)
|
||||||
|
{
|
||||||
|
context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
|
||||||
|
}
|
||||||
|
|
||||||
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
||||||
|
|
||||||
while (mask != 0)
|
while (mask != 0)
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
// Map pages that are already full as RX.
|
// Map pages that are already full as RX.
|
||||||
// Map pages that are not full yet as RWX.
|
// 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 endOffs = offset + size;
|
||||||
|
|
||||||
int pageStart = offset & ~PageMask;
|
int pageStart = offset & ~PageMask;
|
||||||
|
|
|
@ -99,31 +99,48 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
var unwindInfo = funcEntry.UnwindInfo;
|
var unwindInfo = funcEntry.UnwindInfo;
|
||||||
|
|
||||||
_unwindInfo->UnwindCodes[0] = PackUwop(UnwindOperation.AllocLarge, unwindInfo.PrologueSize, 1);
|
int codeIndex = 0;
|
||||||
_unwindInfo->UnwindCodes[1] = (ushort)(unwindInfo.FixedAllocSize >> 0);
|
|
||||||
_unwindInfo->UnwindCodes[2] = (ushort)(unwindInfo.FixedAllocSize >> 16);
|
|
||||||
|
|
||||||
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--)
|
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
|
||||||
{
|
{
|
||||||
var entry = unwindInfo.PushEntries[index];
|
var entry = unwindInfo.PushEntries[index];
|
||||||
|
|
||||||
bool isInteger = entry.Type == RegisterType.Integer;
|
if (entry.Type == RegisterType.Vector)
|
||||||
|
|
||||||
UnwindOperation uwop = isInteger
|
|
||||||
? UnwindOperation.PushNonvol
|
|
||||||
: UnwindOperation.SaveXmm128;
|
|
||||||
|
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUwop(uwop, entry.StreamEndOffset, entry.Index);
|
|
||||||
|
|
||||||
if (!isInteger)
|
|
||||||
{
|
{
|
||||||
|
ushort uwop = PackUwop(UnwindOperation.SaveXmm128, entry.StreamEndOffset, entry.Index);
|
||||||
|
|
||||||
|
_unwindInfo->UnwindCodes[codeIndex++] = uwop;
|
||||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)spOffset;
|
_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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue