1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * thunks.S - assembly helpers for mixed-bitness code
4  * Copyright (c) 2015 Andrew Lutomirski
5  *
6  * These are little helpers that make it easier to switch bitness on
7  * the fly.
8  */
9 
10 	.text
11 
12 	.global call32_from_64
13 	.type call32_from_64, @function
14 call32_from_64:
15 	// rdi: stack to use
16 	// esi: function to call
17 
18 	// Save registers
19 	pushq %rbx
20 	pushq %rbp
21 	pushq %r12
22 	pushq %r13
23 	pushq %r14
24 	pushq %r15
25 	pushfq
26 
27 	// Switch stacks
28 	mov %rsp,(%rdi)
29 	mov %rdi,%rsp
30 
31 	// Switch to compatibility mode
32 	pushq $0x23  /* USER32_CS */
33 	pushq $1f
34 	lretq
35 
36 1:
37 	.code32
38 	// Call the function
39 	call *%esi
40 	// Switch back to long mode
41 	jmp $0x33,$1f
42 	.code64
43 
44 1:
45 	// Restore the stack
46 	mov (%rsp),%rsp
47 
48 	// Restore registers
49 	popfq
50 	popq %r15
51 	popq %r14
52 	popq %r13
53 	popq %r12
54 	popq %rbp
55 	popq %rbx
56 
57 	ret
58 
59 .size call32_from_64, .-call32_from_64
60 
61 .section .note.GNU-stack,"",%progbits
62