diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index f894b53031..62bce1b04b 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -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(); } - 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; diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index af1629314c..acd6f89a3a 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -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) diff --git a/ARMeilleure/Translation/JitCache.cs b/ARMeilleure/Translation/JitCache.cs index f3d21c72d2..2ec76241ca 100644 --- a/ARMeilleure/Translation/JitCache.cs +++ b/ARMeilleure/Translation/JitCache.cs @@ -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; diff --git a/ARMeilleure/Translation/JitUnwindWindows.cs b/ARMeilleure/Translation/JitUnwindWindows.cs index 8c1bcbb39c..6aa58c90b9 100644 --- a/ARMeilleure/Translation/JitUnwindWindows.cs +++ b/ARMeilleure/Translation/JitUnwindWindows.cs @@ -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; } }