]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
UefiCpuPkg/MpInitLib: Use XADD to avoid lock acquire/release
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
4 ;
5 ; Module Name:
6 ;
7 ; MpFuncs.nasm
8 ;
9 ; Abstract:
10 ;
11 ; This is the assembly code for MP support
12 ;
13 ;-------------------------------------------------------------------------------
14
15 %include "MpEqu.inc"
16 extern ASM_PFX(InitializeFloatingPointUnits)
17
18 DEFAULT REL
19
20 SECTION .text
21
22 ;-------------------------------------------------------------------------------------
23 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
24 ;procedure serializes all the AP processors through an Init sequence. It must be
25 ;noted that APs arrive here very raw...ie: real mode, no stack.
26 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
27 ;IS IN MACHINE CODE.
28 ;-------------------------------------------------------------------------------------
29 global ASM_PFX(RendezvousFunnelProc)
30 ASM_PFX(RendezvousFunnelProc):
31 RendezvousFunnelProcStart:
32 ; At this point CS = 0x(vv00) and ip= 0x0.
33 ; Save BIST information to ebp firstly
34
35 BITS 16
36 mov ebp, eax ; Save BIST information
37
38 mov ax, cs
39 mov ds, ax
40 mov es, ax
41 mov ss, ax
42 xor ax, ax
43 mov fs, ax
44 mov gs, ax
45
46 mov si, BufferStartLocation
47 mov ebx, [si]
48
49 mov si, DataSegmentLocation
50 mov edx, [si]
51
52 ;
53 ; Get start address of 32-bit code in low memory (<1MB)
54 ;
55 mov edi, ModeTransitionMemoryLocation
56
57 mov si, GdtrLocation
58 o32 lgdt [cs:si]
59
60 mov si, IdtrLocation
61 o32 lidt [cs:si]
62
63 ;
64 ; Switch to protected mode
65 ;
66 mov eax, cr0 ; Get control register 0
67 or eax, 000000003h ; Set PE bit (bit #0) & MP
68 mov cr0, eax
69
70 ; Switch to 32-bit code (>1MB)
71 o32 jmp far [cs:di]
72
73 ;
74 ; Following code must be copied to memory with type of EfiBootServicesCode.
75 ; This is required if NX is enabled for EfiBootServicesCode of memory.
76 ;
77 BITS 32
78 Flat32Start: ; protected mode entry point
79 mov ds, dx
80 mov es, dx
81 mov fs, dx
82 mov gs, dx
83 mov ss, dx
84
85 ;
86 ; Enable execute disable bit
87 ;
88 mov esi, EnableExecuteDisableLocation
89 cmp byte [ebx + esi], 0
90 jz SkipEnableExecuteDisableBit
91
92 mov ecx, 0c0000080h ; EFER MSR number
93 rdmsr ; Read EFER
94 bts eax, 11 ; Enable Execute Disable Bit
95 wrmsr ; Write EFER
96
97 SkipEnableExecuteDisableBit:
98 ;
99 ; Enable PAE
100 ;
101 mov eax, cr4
102 bts eax, 5
103
104 mov esi, Enable5LevelPagingLocation
105 cmp byte [ebx + esi], 0
106 jz SkipEnable5LevelPaging
107
108 ;
109 ; Enable 5 Level Paging
110 ;
111 bts eax, 12 ; Set LA57=1.
112
113 SkipEnable5LevelPaging:
114
115 mov cr4, eax
116
117 ;
118 ; Load page table
119 ;
120 mov esi, Cr3Location ; Save CR3 in ecx
121 mov ecx, [ebx + esi]
122 mov cr3, ecx ; Load CR3
123
124 ;
125 ; Enable long mode
126 ;
127 mov ecx, 0c0000080h ; EFER MSR number
128 rdmsr ; Read EFER
129 bts eax, 8 ; Set LME=1
130 wrmsr ; Write EFER
131
132 ;
133 ; Enable paging
134 ;
135 mov eax, cr0 ; Read CR0
136 bts eax, 31 ; Set PG=1
137 mov cr0, eax ; Write CR0
138
139 ;
140 ; Far jump to 64-bit code
141 ;
142 mov edi, ModeHighMemoryLocation
143 add edi, ebx
144 jmp far [edi]
145
146 BITS 64
147 LongModeStart:
148 mov esi, ebx
149 lea edi, [esi + InitFlagLocation]
150 cmp qword [edi], 1 ; ApInitConfig
151 jnz GetApicId
152
153 ; Increment the number of APs executing here as early as possible
154 ; This is decremented in C code when AP is finished executing
155 mov edi, esi
156 add edi, NumApsExecutingLocation
157 lock inc dword [edi]
158
159 ; AP init
160 mov edi, esi
161 add edi, LockLocation
162 mov rax, NotVacantFlag
163
164 mov edi, esi
165 add edi, ApIndexLocation
166 mov ebx, 1
167 lock xadd dword [edi], ebx ; EBX = ApIndex++
168 inc ebx ; EBX is CpuNumber
169
170 ; program stack
171 mov edi, esi
172 add edi, StackSizeLocation
173 mov eax, dword [edi]
174 mov ecx, ebx
175 inc ecx
176 mul ecx ; EAX = StackSize * (CpuNumber + 1)
177 mov edi, esi
178 add edi, StackStartAddressLocation
179 add rax, qword [edi]
180 mov rsp, rax
181
182 lea edi, [esi + SevEsIsEnabledLocation]
183 cmp byte [edi], 1 ; SevEsIsEnabled
184 jne CProcedureInvoke
185
186 ;
187 ; program GHCB
188 ; Each page after the GHCB is a per-CPU page, so the calculation programs
189 ; a GHCB to be every 8KB.
190 ;
191 mov eax, SIZE_4KB
192 shl eax, 1 ; EAX = SIZE_4K * 2
193 mov ecx, ebx
194 mul ecx ; EAX = SIZE_4K * 2 * CpuNumber
195 mov edi, esi
196 add edi, GhcbBaseLocation
197 add rax, qword [edi]
198 mov rdx, rax
199 shr rdx, 32
200 mov rcx, 0xc0010130
201 wrmsr
202 jmp CProcedureInvoke
203
204 GetApicId:
205 lea edi, [esi + SevEsIsEnabledLocation]
206 cmp byte [edi], 1 ; SevEsIsEnabled
207 jne DoCpuid
208
209 ;
210 ; Since we don't have a stack yet, we can't take a #VC
211 ; exception. Use the GHCB protocol to perform the CPUID
212 ; calls.
213 ;
214 mov rcx, 0xc0010130
215 rdmsr
216 shl rdx, 32
217 or rax, rdx
218 mov rdi, rax ; RDI now holds the original GHCB GPA
219
220 mov rdx, 0 ; CPUID function 0
221 mov rax, 0 ; RAX register requested
222 or rax, 4
223 wrmsr
224 rep vmmcall
225 rdmsr
226 cmp edx, 0bh
227 jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOPOLOGY
228
229 mov rdx, 0bh ; CPUID function 0x0b
230 mov rax, 040000000h ; RBX register requested
231 or rax, 4
232 wrmsr
233 rep vmmcall
234 rdmsr
235 test edx, 0ffffh
236 jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero
237
238 mov rdx, 0bh ; CPUID function 0x0b
239 mov rax, 0c0000000h ; RDX register requested
240 or rax, 4
241 wrmsr
242 rep vmmcall
243 rdmsr
244
245 ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
246 jmp RestoreGhcb
247
248 NoX2ApicSevEs:
249 ; Processor is not x2APIC capable, so get 8-bit APIC ID
250 mov rdx, 1 ; CPUID function 1
251 mov rax, 040000000h ; RBX register requested
252 or rax, 4
253 wrmsr
254 rep vmmcall
255 rdmsr
256 shr edx, 24
257
258 RestoreGhcb:
259 mov rbx, rdx ; Save x2APIC/APIC ID
260
261 mov rdx, rdi ; RDI holds the saved GHCB GPA
262 shr rdx, 32
263 mov eax, edi
264 wrmsr
265
266 mov rdx, rbx
267
268 ; x2APIC ID or APIC ID is in EDX
269 jmp GetProcessorNumber
270
271 DoCpuid:
272 mov eax, 0
273 cpuid
274 cmp eax, 0bh
275 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
276
277 mov eax, 0bh
278 xor ecx, ecx
279 cpuid
280 test ebx, 0ffffh
281 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
282
283 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
284 jmp GetProcessorNumber
285
286 NoX2Apic:
287 ; Processor is not x2APIC capable, so get 8-bit APIC ID
288 mov eax, 1
289 cpuid
290 shr ebx, 24
291 mov edx, ebx
292
293 GetProcessorNumber:
294 ;
295 ; Get processor number for this AP
296 ; Note that BSP may become an AP due to SwitchBsp()
297 ;
298 xor ebx, ebx
299 lea eax, [esi + CpuInfoLocation]
300 mov rdi, [eax]
301
302 GetNextProcNumber:
303 cmp dword [rdi], edx ; APIC ID match?
304 jz ProgramStack
305 add rdi, 20
306 inc ebx
307 jmp GetNextProcNumber
308
309 ProgramStack:
310 mov rsp, qword [rdi + 12]
311
312 CProcedureInvoke:
313 push rbp ; Push BIST data at top of AP stack
314 xor rbp, rbp ; Clear ebp for call stack trace
315 push rbp
316 mov rbp, rsp
317
318 mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
319 sub rsp, 20h
320 call rax ; Call assembly function to initialize FPU per UEFI spec
321 add rsp, 20h
322
323 mov edx, ebx ; edx is ApIndex
324 mov ecx, esi
325 add ecx, LockLocation ; rcx is address of exchange info data buffer
326
327 mov edi, esi
328 add edi, ApProcedureLocation
329 mov rax, qword [edi]
330
331 sub rsp, 20h
332 call rax ; Invoke C function
333 add rsp, 20h
334 jmp $ ; Should never reach here
335
336 RendezvousFunnelProcEnd:
337
338 ;-------------------------------------------------------------------------------------
339 ;SwitchToRealProc procedure follows.
340 ;ALSO THIS PROCEDURE IS EXECUTED BY APs TRANSITIONING TO 16 BIT MODE. HENCE THIS PROC
341 ;IS IN MACHINE CODE.
342 ; SwitchToRealProc (UINTN BufferStart, UINT16 Code16, UINT16 Code32, UINTN StackStart)
343 ; rcx - Buffer Start
344 ; rdx - Code16 Selector Offset
345 ; r8 - Code32 Selector Offset
346 ; r9 - Stack Start
347 ;-------------------------------------------------------------------------------------
348 global ASM_PFX(SwitchToRealProc)
349 ASM_PFX(SwitchToRealProc):
350 SwitchToRealProcStart:
351 BITS 64
352 cli
353
354 ;
355 ; Get RDX reset value before changing stacks since the
356 ; new stack won't be able to accomodate a #VC exception.
357 ;
358 push rax
359 push rbx
360 push rcx
361 push rdx
362
363 mov rax, 1
364 cpuid
365 mov rsi, rax ; Save off the reset value for RDX
366
367 pop rdx
368 pop rcx
369 pop rbx
370 pop rax
371
372 ;
373 ; Establish stack below 1MB
374 ;
375 mov rsp, r9
376
377 ;
378 ; Push ultimate Reset Vector onto the stack
379 ;
380 mov rax, rcx
381 shr rax, 4
382 push word 0x0002 ; RFLAGS
383 push ax ; CS
384 push word 0x0000 ; RIP
385 push word 0x0000 ; For alignment, will be discarded
386
387 ;
388 ; Get address of "16-bit operand size" label
389 ;
390 lea rbx, [PM16Mode]
391
392 ;
393 ; Push addresses used to change to compatibility mode
394 ;
395 lea rax, [CompatMode]
396 push r8
397 push rax
398
399 ;
400 ; Clear R8 - R15, for reset, before going into 32-bit mode
401 ;
402 xor r8, r8
403 xor r9, r9
404 xor r10, r10
405 xor r11, r11
406 xor r12, r12
407 xor r13, r13
408 xor r14, r14
409 xor r15, r15
410
411 ;
412 ; Far return into 32-bit mode
413 ;
414 o64 retf
415
416 BITS 32
417 CompatMode:
418 ;
419 ; Set up stack to prepare for exiting protected mode
420 ;
421 push edx ; Code16 CS
422 push ebx ; PM16Mode label address
423
424 ;
425 ; Disable paging
426 ;
427 mov eax, cr0 ; Read CR0
428 btr eax, 31 ; Set PG=0
429 mov cr0, eax ; Write CR0
430
431 ;
432 ; Disable long mode
433 ;
434 mov ecx, 0c0000080h ; EFER MSR number
435 rdmsr ; Read EFER
436 btr eax, 8 ; Set LME=0
437 wrmsr ; Write EFER
438
439 ;
440 ; Disable PAE
441 ;
442 mov eax, cr4 ; Read CR4
443 btr eax, 5 ; Set PAE=0
444 mov cr4, eax ; Write CR4
445
446 mov edx, esi ; Restore RDX reset value
447
448 ;
449 ; Switch to 16-bit operand size
450 ;
451 retf
452
453 BITS 16
454 ;
455 ; At entry to this label
456 ; - RDX will have its reset value
457 ; - On the top of the stack
458 ; - Alignment data (two bytes) to be discarded
459 ; - IP for Real Mode (two bytes)
460 ; - CS for Real Mode (two bytes)
461 ;
462 ; This label is also used with AsmRelocateApLoop. During MP finalization,
463 ; the code from PM16Mode to SwitchToRealProcEnd is copied to the start of
464 ; the WakeupBuffer, allowing a parked AP to be booted by an OS.
465 ;
466 PM16Mode:
467 mov eax, cr0 ; Read CR0
468 btr eax, 0 ; Set PE=0
469 mov cr0, eax ; Write CR0
470
471 pop ax ; Discard alignment data
472
473 ;
474 ; Clear registers (except RDX and RSP) before going into 16-bit mode
475 ;
476 xor eax, eax
477 xor ebx, ebx
478 xor ecx, ecx
479 xor esi, esi
480 xor edi, edi
481 xor ebp, ebp
482
483 iret
484
485 SwitchToRealProcEnd:
486
487 ;-------------------------------------------------------------------------------------
488 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
489 ;-------------------------------------------------------------------------------------
490 global ASM_PFX(AsmRelocateApLoop)
491 ASM_PFX(AsmRelocateApLoop):
492 AsmRelocateApLoopStart:
493 BITS 64
494 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable
495 je NoSevEs
496
497 ;
498 ; Perform some SEV-ES related setup before leaving 64-bit mode
499 ;
500 push rcx
501 push rdx
502
503 ;
504 ; Get the RDX reset value using CPUID
505 ;
506 mov rax, 1
507 cpuid
508 mov rsi, rax ; Save off the reset value for RDX
509
510 ;
511 ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call
512 ; - Must be done while in 64-bit long mode so that writes to
513 ; the GHCB memory will be unencrypted.
514 ; - No NAE events can be generated once this is set otherwise
515 ; the AP_RESET_HOLD SW_EXITCODE will be overwritten.
516 ;
517 mov rcx, 0xc0010130
518 rdmsr ; Retrieve current GHCB address
519 shl rdx, 32
520 or rdx, rax
521
522 mov rdi, rdx
523 xor rax, rax
524 mov rcx, 0x800
525 shr rcx, 3
526 rep stosq ; Clear the GHCB
527
528 mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD
529 mov [rdx + 0x390], rax
530 mov rax, 114 ; Set SwExitCode valid bit
531 bts [rdx + 0x3f0], rax
532 inc rax ; Set SwExitInfo1 valid bit
533 bts [rdx + 0x3f0], rax
534 inc rax ; Set SwExitInfo2 valid bit
535 bts [rdx + 0x3f0], rax
536
537 pop rdx
538 pop rcx
539
540 NoSevEs:
541 cli ; Disable interrupt before switching to 32-bit mode
542 mov rax, [rsp + 40] ; CountTofinish
543 lock dec dword [rax] ; (*CountTofinish)--
544
545 mov r10, [rsp + 48] ; Pm16CodeSegment
546 mov rax, [rsp + 56] ; SevEsAPJumpTable
547 mov rbx, [rsp + 64] ; WakeupBuffer
548 mov rsp, r9 ; TopOfApStack
549
550 push rax ; Save SevEsAPJumpTable
551 push rbx ; Save WakeupBuffer
552 push r10 ; Save Pm16CodeSegment
553 push rcx ; Save MwaitSupport
554 push rdx ; Save ApTargetCState
555
556 lea rax, [PmEntry] ; rax <- The start address of transition code
557
558 push r8
559 push rax
560
561 ;
562 ; Clear R8 - R15, for reset, before going into 32-bit mode
563 ;
564 xor r8, r8
565 xor r9, r9
566 xor r10, r10
567 xor r11, r11
568 xor r12, r12
569 xor r13, r13
570 xor r14, r14
571 xor r15, r15
572
573 ;
574 ; Far return into 32-bit mode
575 ;
576 o64 retf
577
578 BITS 32
579 PmEntry:
580 mov eax, cr0
581 btr eax, 31 ; Clear CR0.PG
582 mov cr0, eax ; Disable paging and caches
583
584 mov ecx, 0xc0000080
585 rdmsr
586 and ah, ~ 1 ; Clear LME
587 wrmsr
588 mov eax, cr4
589 and al, ~ (1 << 5) ; Clear PAE
590 mov cr4, eax
591
592 pop edx
593 add esp, 4
594 pop ecx,
595 add esp, 4
596
597 MwaitCheck:
598 cmp cl, 1 ; Check mwait-monitor support
599 jnz HltLoop
600 mov ebx, edx ; Save C-State to ebx
601 MwaitLoop:
602 cli
603 mov eax, esp ; Set Monitor Address
604 xor ecx, ecx ; ecx = 0
605 xor edx, edx ; edx = 0
606 monitor
607 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
608 shl eax, 4
609 mwait
610 jmp MwaitLoop
611
612 HltLoop:
613 pop edx ; PM16CodeSegment
614 add esp, 4
615 pop ebx ; WakeupBuffer
616 add esp, 4
617 pop eax ; SevEsAPJumpTable
618 add esp, 4
619 cmp eax, 0 ; Check for SEV-ES
620 je DoHlt
621
622 cli
623 ;
624 ; SEV-ES is enabled, use VMGEXIT (GHCB information already
625 ; set by caller)
626 ;
627 BITS 64
628 rep vmmcall
629 BITS 32
630
631 ;
632 ; Back from VMGEXIT AP_HLT_LOOP
633 ; Push the FLAGS/CS/IP values to use
634 ;
635 push word 0x0002 ; EFLAGS
636 xor ecx, ecx
637 mov cx, [eax + 2] ; CS
638 push cx
639 mov cx, [eax] ; IP
640 push cx
641 push word 0x0000 ; For alignment, will be discarded
642
643 push edx
644 push ebx
645
646 mov edx, esi ; Restore RDX reset value
647
648 retf
649
650 DoHlt:
651 cli
652 hlt
653 jmp DoHlt
654
655 BITS 64
656 AsmRelocateApLoopEnd:
657
658 ;-------------------------------------------------------------------------------------
659 ; AsmGetAddressMap (&AddressMap);
660 ;-------------------------------------------------------------------------------------
661 global ASM_PFX(AsmGetAddressMap)
662 ASM_PFX(AsmGetAddressMap):
663 lea rax, [ASM_PFX(RendezvousFunnelProc)]
664 mov qword [rcx], rax
665 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
666 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
667 lea rax, [ASM_PFX(AsmRelocateApLoop)]
668 mov qword [rcx + 18h], rax
669 mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
670 mov qword [rcx + 28h], Flat32Start - RendezvousFunnelProcStart
671 mov qword [rcx + 30h], SwitchToRealProcEnd - SwitchToRealProcStart ; SwitchToRealSize
672 mov qword [rcx + 38h], SwitchToRealProcStart - RendezvousFunnelProcStart ; SwitchToRealOffset
673 mov qword [rcx + 40h], SwitchToRealProcStart - Flat32Start ; SwitchToRealNoNxOffset
674 mov qword [rcx + 48h], PM16Mode - RendezvousFunnelProcStart ; SwitchToRealPM16ModeOffset
675 mov qword [rcx + 50h], SwitchToRealProcEnd - PM16Mode ; SwitchToRealPM16ModeSize
676 ret
677
678 ;-------------------------------------------------------------------------------------
679 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
680 ;about to become an AP. It switches its stack with the current AP.
681 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
682 ;-------------------------------------------------------------------------------------
683 global ASM_PFX(AsmExchangeRole)
684 ASM_PFX(AsmExchangeRole):
685 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
686 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
687
688 push rax
689 push rbx
690 push rcx
691 push rdx
692 push rsi
693 push rdi
694 push rbp
695 push r8
696 push r9
697 push r10
698 push r11
699 push r12
700 push r13
701 push r14
702 push r15
703
704 mov rax, cr0
705 push rax
706
707 mov rax, cr4
708 push rax
709
710 ; rsi contains MyInfo pointer
711 mov rsi, rcx
712
713 ; rdi contains OthersInfo pointer
714 mov rdi, rdx
715
716 ;Store EFLAGS, GDTR and IDTR regiter to stack
717 pushfq
718 sgdt [rsi + 16]
719 sidt [rsi + 26]
720
721 ; Store the its StackPointer
722 mov [rsi + 8], rsp
723
724 ; update its switch state to STORED
725 mov byte [rsi], CPU_SWITCH_STATE_STORED
726
727 WaitForOtherStored:
728 ; wait until the other CPU finish storing its state
729 cmp byte [rdi], CPU_SWITCH_STATE_STORED
730 jz OtherStored
731 pause
732 jmp WaitForOtherStored
733
734 OtherStored:
735 ; Since another CPU already stored its state, load them
736 ; load GDTR value
737 lgdt [rdi + 16]
738
739 ; load IDTR value
740 lidt [rdi + 26]
741
742 ; load its future StackPointer
743 mov rsp, [rdi + 8]
744
745 ; update the other CPU's switch state to LOADED
746 mov byte [rdi], CPU_SWITCH_STATE_LOADED
747
748 WaitForOtherLoaded:
749 ; wait until the other CPU finish loading new state,
750 ; otherwise the data in stack may corrupt
751 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
752 jz OtherLoaded
753 pause
754 jmp WaitForOtherLoaded
755
756 OtherLoaded:
757 ; since the other CPU already get the data it want, leave this procedure
758 popfq
759
760 pop rax
761 mov cr4, rax
762
763 pop rax
764 mov cr0, rax
765
766 pop r15
767 pop r14
768 pop r13
769 pop r12
770 pop r11
771 pop r10
772 pop r9
773 pop r8
774 pop rbp
775 pop rdi
776 pop rsi
777 pop rdx
778 pop rcx
779 pop rbx
780 pop rax
781
782 ret