コード例 #1
0
        private static unsafe RuntimeFunction *FunctionTableHandler(ulong controlPc, IntPtr context)
        {
            int offset = (int)((long)controlPc - context.ToInt64());

            if (!JitCache.TryFind(offset, out JitCacheEntry funcEntry))
            {
                // Not found.
                return(null);
            }

            var unwindInfo = funcEntry.UnwindInfo;

            int codeIndex = 0;

            int spOffset = unwindInfo.FixedAllocSize;

            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];

                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;
                }
            }

            _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;
                }
            }

            _unwindInfo->VersionAndFlags    = 1;
            _unwindInfo->SizeOfProlog       = (byte)unwindInfo.PrologueSize;
            _unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
            _unwindInfo->FrameRegister      = 0;

            _runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
            _runtimeFunction->EndAddress   = (uint)(funcEntry.Offset + funcEntry.Size);
            _runtimeFunction->UnwindData   = (uint)_sizeOfRuntimeFunction;

            return(_runtimeFunction);
        }
コード例 #2
0
ファイル: JitUnwindWindows.cs プロジェクト: turbedi/Ryujinx
        private static unsafe RuntimeFunction *FunctionTableHandler(ulong controlPc, IntPtr context)
        {
            int offset = (int)((long)controlPc - context.ToInt64());

            if (!JitCache.TryFind(offset, out JitCacheEntry funcEntry))
            {
                return(null); // Not found.
            }

            var unwindInfo = funcEntry.UnwindInfo;

            int codeIndex = 0;

            for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
            {
                var entry = unwindInfo.PushEntries[index];

                switch (entry.PseudoOp)
                {
                case UnwindPseudoOp.SaveXmm128:
                {
                    int stackOffset = entry.StackOffsetOrAllocSize;

                    Debug.Assert(stackOffset % 16 == 0);

                    if (stackOffset <= 0xFFFF0)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.SaveXmm128, entry.PrologOffset, entry.RegIndex);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
                    }
                    else
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
                    }

                    break;
                }

                case UnwindPseudoOp.AllocStack:
                {
                    int allocSize = entry.StackOffsetOrAllocSize;

                    Debug.Assert(allocSize % 8 == 0);

                    if (allocSize <= 128)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
                    }
                    else if (allocSize <= 0x7FFF8)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocLarge, entry.PrologOffset, 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
                    }
                    else
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocLarge, entry.PrologOffset, 1);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
                    }

                    break;
                }

                case UnwindPseudoOp.PushReg:
                {
                    _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.PushNonvol, entry.PrologOffset, entry.RegIndex);

                    break;
                }

                default: throw new NotImplementedException($"({nameof(entry.PseudoOp)} = {entry.PseudoOp})");
                }
            }

            Debug.Assert(codeIndex <= MaxUnwindCodesArraySize);

            _unwindInfo->VersionAndFlags    = 1; // Flags: The function has no handler.
            _unwindInfo->SizeOfProlog       = (byte)unwindInfo.PrologSize;
            _unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
            _unwindInfo->FrameRegister      = 0;

            _runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
            _runtimeFunction->EndAddress   = (uint)(funcEntry.Offset + funcEntry.Size);
            _runtimeFunction->UnwindData   = (uint)_sizeOfRuntimeFunction;

            return(_runtimeFunction);
        }