mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 17:09:57 -04:00
- The mesh stage's storage table starts 0x90 bytes before the end of the 2 KiB constant bank, and all sixteen slots were written: 0x6C bytes past a stack buffer on every mesh draw. It holds the nine slots that fit. - The prebuilt runtime is compiled without AVX, so its preemption stub saved only XMM0-15 while the lifted code of an AVX2 processor keeps data in the upper YMM halves, which the stub's callees may clear. Both bodies are built now and the one for the processor is chosen at the start. - After an FSR 3.1 frame generation error the window's swapchain was still AMD's object but went to the plain Vulkan calls. Swapchain calls follow whose swapchain it is, and a failure takes it down as a switch in the menu does. - A movie is paced at its own 60 fps under a lower limit too: at 40 fps it ended 25 s behind its sound. - A lost device left the wait for an upload spinning for good; it ends the run with the device's report. - The compute pipeline key had four bytes of padding that were hashed and compared, so a prebuilt pipeline could be missed and built again. - A thread's TLS pointer was published before the TLS was allocated, so the slot was always 0. - A fatal exit puts RivaTuner Statistics Server's profile back, and an ini saved as UTF-16 is read. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
173 lines
7.0 KiB
C
173 lines
7.0 KiB
C
// The body of kern_ap_stub (kernel.c, "asynchronous preemption"), included once per register width with AP_NAME the
|
|
// function's name, AP_VMOV and AP_V the move and the register prefix that save the vector registers, and AP_VZEROUPPER
|
|
// the instruction that ends the use of the upper halves (or nothing). No include guard: kernel.c includes it twice.
|
|
#ifdef _WIN32
|
|
__asm__(".text\n"
|
|
".globl " AP_NAME "\n"
|
|
".def " AP_NAME "; .scl 2; .type 32; .endef\n"
|
|
".p2align 4\n"
|
|
AP_NAME ":\n"
|
|
".seh_proc " AP_NAME "\n"
|
|
" leaq -8(%rsp), %rsp\n" // not sub: the flags are still the interrupted code's until pushfq
|
|
".seh_stackalloc 8\n"
|
|
" pushfq\n"
|
|
".seh_stackalloc 8\n"
|
|
" pushq %rax\n"
|
|
".seh_pushreg %rax\n"
|
|
" pushq %rcx\n"
|
|
".seh_pushreg %rcx\n"
|
|
" pushq %rdx\n"
|
|
".seh_pushreg %rdx\n"
|
|
" pushq %r8\n"
|
|
".seh_pushreg %r8\n"
|
|
" pushq %r9\n"
|
|
".seh_pushreg %r9\n"
|
|
" pushq %r10\n"
|
|
".seh_pushreg %r10\n"
|
|
" pushq %r11\n"
|
|
".seh_pushreg %r11\n"
|
|
" pushq %rbp\n"
|
|
".seh_pushreg %rbp\n"
|
|
" movq %rsp, %rbp\n"
|
|
".seh_setframe %rbp, 0\n"
|
|
".seh_endprologue\n"
|
|
" andq $-32, %rsp\n"
|
|
" subq $576, %rsp\n" // 0: shadow space, 32: MXCSR saved, 36: MXCSR default, 64: YMM0-15 (XMM0-15 without AVX)
|
|
" " AP_VMOV " " AP_V "0, 64(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "1, 96(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "2, 128(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "3, 160(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "4, 192(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "5, 224(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "6, 256(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "7, 288(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "8, 320(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "9, 352(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "10, 384(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "11, 416(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "12, 448(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "13, 480(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "14, 512(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "15, 544(%rsp)\n"
|
|
" stmxcsr 32(%rsp)\n"
|
|
" movl $0x1f80, 36(%rsp)\n"
|
|
" ldmxcsr 36(%rsp)\n"
|
|
" cld\n"
|
|
AP_VZEROUPPER
|
|
" call kern_ap_rip\n"
|
|
" movq %rax, 72(%rbp)\n" // the return slot: rbp + 8 pushes + pushfq
|
|
" call kern_ap_yield\n"
|
|
" ldmxcsr 32(%rsp)\n"
|
|
" " AP_VMOV " 64(%rsp), " AP_V "0\n"
|
|
" " AP_VMOV " 96(%rsp), " AP_V "1\n"
|
|
" " AP_VMOV " 128(%rsp), " AP_V "2\n"
|
|
" " AP_VMOV " 160(%rsp), " AP_V "3\n"
|
|
" " AP_VMOV " 192(%rsp), " AP_V "4\n"
|
|
" " AP_VMOV " 224(%rsp), " AP_V "5\n"
|
|
" " AP_VMOV " 256(%rsp), " AP_V "6\n"
|
|
" " AP_VMOV " 288(%rsp), " AP_V "7\n"
|
|
" " AP_VMOV " 320(%rsp), " AP_V "8\n"
|
|
" " AP_VMOV " 352(%rsp), " AP_V "9\n"
|
|
" " AP_VMOV " 384(%rsp), " AP_V "10\n"
|
|
" " AP_VMOV " 416(%rsp), " AP_V "11\n"
|
|
" " AP_VMOV " 448(%rsp), " AP_V "12\n"
|
|
" " AP_VMOV " 480(%rsp), " AP_V "13\n"
|
|
" " AP_VMOV " 512(%rsp), " AP_V "14\n"
|
|
" " AP_VMOV " 544(%rsp), " AP_V "15\n"
|
|
" movq %rbp, %rsp\n"
|
|
" popq %rbp\n"
|
|
" popq %r11\n"
|
|
" popq %r10\n"
|
|
" popq %r9\n"
|
|
" popq %r8\n"
|
|
" popq %rdx\n"
|
|
" popq %rcx\n"
|
|
" popq %rax\n"
|
|
" popfq\n"
|
|
" leaq 8(%rsp), %rsp\n"
|
|
" jmpq *-8(%rsp)\n"
|
|
".seh_endproc\n");
|
|
#else
|
|
// The System V version: rsi and rdi are volatile there too, and the interrupted code may keep data in the 128 bytes
|
|
// below its stack pointer (the red zone), so the return slot and the saves go below that. Without a red zone in the
|
|
// way the slot is at entry - 136; the exit restores rsp to the entry value and jumps through the slot.
|
|
__asm__(".text\n"
|
|
".globl " AP_NAME "\n"
|
|
".type " AP_NAME ", @function\n"
|
|
".p2align 4\n"
|
|
AP_NAME ":\n"
|
|
" .cfi_startproc\n"
|
|
" leaq -136(%rsp), %rsp\n" // not sub: the flags are still the interrupted code's until pushfq
|
|
" pushfq\n"
|
|
" pushq %rax\n"
|
|
" pushq %rcx\n"
|
|
" pushq %rdx\n"
|
|
" pushq %rsi\n"
|
|
" pushq %rdi\n"
|
|
" pushq %r8\n"
|
|
" pushq %r9\n"
|
|
" pushq %r10\n"
|
|
" pushq %r11\n"
|
|
" pushq %rbp\n"
|
|
" movq %rsp, %rbp\n"
|
|
" andq $-32, %rsp\n"
|
|
" subq $576, %rsp\n" // 32: MXCSR saved, 36: MXCSR default, 64: YMM0-15 (XMM0-15 without AVX)
|
|
" " AP_VMOV " " AP_V "0, 64(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "1, 96(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "2, 128(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "3, 160(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "4, 192(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "5, 224(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "6, 256(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "7, 288(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "8, 320(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "9, 352(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "10, 384(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "11, 416(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "12, 448(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "13, 480(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "14, 512(%rsp)\n"
|
|
" " AP_VMOV " " AP_V "15, 544(%rsp)\n"
|
|
" stmxcsr 32(%rsp)\n"
|
|
" movl $0x1f80, 36(%rsp)\n"
|
|
" ldmxcsr 36(%rsp)\n"
|
|
" cld\n"
|
|
AP_VZEROUPPER
|
|
" call kern_ap_rip\n"
|
|
" movq %rax, 88(%rbp)\n" // the return slot: rbp + 10 pushes + pushfq
|
|
" call kern_ap_yield\n"
|
|
" ldmxcsr 32(%rsp)\n"
|
|
" " AP_VMOV " 64(%rsp), " AP_V "0\n"
|
|
" " AP_VMOV " 96(%rsp), " AP_V "1\n"
|
|
" " AP_VMOV " 128(%rsp), " AP_V "2\n"
|
|
" " AP_VMOV " 160(%rsp), " AP_V "3\n"
|
|
" " AP_VMOV " 192(%rsp), " AP_V "4\n"
|
|
" " AP_VMOV " 224(%rsp), " AP_V "5\n"
|
|
" " AP_VMOV " 256(%rsp), " AP_V "6\n"
|
|
" " AP_VMOV " 288(%rsp), " AP_V "7\n"
|
|
" " AP_VMOV " 320(%rsp), " AP_V "8\n"
|
|
" " AP_VMOV " 352(%rsp), " AP_V "9\n"
|
|
" " AP_VMOV " 384(%rsp), " AP_V "10\n"
|
|
" " AP_VMOV " 416(%rsp), " AP_V "11\n"
|
|
" " AP_VMOV " 448(%rsp), " AP_V "12\n"
|
|
" " AP_VMOV " 480(%rsp), " AP_V "13\n"
|
|
" " AP_VMOV " 512(%rsp), " AP_V "14\n"
|
|
" " AP_VMOV " 544(%rsp), " AP_V "15\n"
|
|
" movq %rbp, %rsp\n"
|
|
" popq %rbp\n"
|
|
" popq %r11\n"
|
|
" popq %r10\n"
|
|
" popq %r9\n"
|
|
" popq %r8\n"
|
|
" popq %rdi\n"
|
|
" popq %rsi\n"
|
|
" popq %rdx\n"
|
|
" popq %rcx\n"
|
|
" popq %rax\n"
|
|
" popfq\n"
|
|
" leaq 136(%rsp), %rsp\n"
|
|
" jmpq *-136(%rsp)\n"
|
|
" .cfi_endproc\n"
|
|
".size " AP_NAME ", .-" AP_NAME "\n");
|
|
#endif
|