1e22438f8SAndy Lutomirski/*
2e22438f8SAndy Lutomirski * thunks.S - assembly helpers for mixed-bitness code
3e22438f8SAndy Lutomirski * Copyright (c) 2015 Andrew Lutomirski
4e22438f8SAndy Lutomirski *
5e22438f8SAndy Lutomirski * This program is free software; you can redistribute it and/or modify
6e22438f8SAndy Lutomirski * it under the terms and conditions of the GNU General Public License,
7e22438f8SAndy Lutomirski * version 2, as published by the Free Software Foundation.
8e22438f8SAndy Lutomirski *
9e22438f8SAndy Lutomirski * This program is distributed in the hope it will be useful, but
10e22438f8SAndy Lutomirski * WITHOUT ANY WARRANTY; without even the implied warranty of
11e22438f8SAndy Lutomirski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12e22438f8SAndy Lutomirski * General Public License for more details.
13e22438f8SAndy Lutomirski *
14e22438f8SAndy Lutomirski * These are little helpers that make it easier to switch bitness on
15e22438f8SAndy Lutomirski * the fly.
16e22438f8SAndy Lutomirski */
17e22438f8SAndy Lutomirski
18e22438f8SAndy Lutomirski	.text
19e22438f8SAndy Lutomirski
20e22438f8SAndy Lutomirski	.global call32_from_64
21e22438f8SAndy Lutomirski	.type call32_from_64, @function
22e22438f8SAndy Lutomirskicall32_from_64:
23e22438f8SAndy Lutomirski	// rdi: stack to use
24e22438f8SAndy Lutomirski	// esi: function to call
25e22438f8SAndy Lutomirski
26e22438f8SAndy Lutomirski	// Save registers
27e22438f8SAndy Lutomirski	pushq %rbx
28e22438f8SAndy Lutomirski	pushq %rbp
29e22438f8SAndy Lutomirski	pushq %r12
30e22438f8SAndy Lutomirski	pushq %r13
31e22438f8SAndy Lutomirski	pushq %r14
32e22438f8SAndy Lutomirski	pushq %r15
33e22438f8SAndy Lutomirski	pushfq
34e22438f8SAndy Lutomirski
35e22438f8SAndy Lutomirski	// Switch stacks
36e22438f8SAndy Lutomirski	mov %rsp,(%rdi)
37e22438f8SAndy Lutomirski	mov %rdi,%rsp
38e22438f8SAndy Lutomirski
39e22438f8SAndy Lutomirski	// Switch to compatibility mode
40e22438f8SAndy Lutomirski	pushq $0x23  /* USER32_CS */
41e22438f8SAndy Lutomirski	pushq $1f
42e22438f8SAndy Lutomirski	lretq
43e22438f8SAndy Lutomirski
44e22438f8SAndy Lutomirski1:
45e22438f8SAndy Lutomirski	.code32
46e22438f8SAndy Lutomirski	// Call the function
47e22438f8SAndy Lutomirski	call *%esi
48e22438f8SAndy Lutomirski	// Switch back to long mode
49e22438f8SAndy Lutomirski	jmp $0x33,$1f
50e22438f8SAndy Lutomirski	.code64
51e22438f8SAndy Lutomirski
52e22438f8SAndy Lutomirski1:
53e22438f8SAndy Lutomirski	// Restore the stack
54e22438f8SAndy Lutomirski	mov (%rsp),%rsp
55e22438f8SAndy Lutomirski
56e22438f8SAndy Lutomirski	// Restore registers
57e22438f8SAndy Lutomirski	popfq
58e22438f8SAndy Lutomirski	popq %r15
59e22438f8SAndy Lutomirski	popq %r14
60e22438f8SAndy Lutomirski	popq %r13
61e22438f8SAndy Lutomirski	popq %r12
62e22438f8SAndy Lutomirski	popq %rbp
63e22438f8SAndy Lutomirski	popq %rbx
64e22438f8SAndy Lutomirski
65e22438f8SAndy Lutomirski	ret
66e22438f8SAndy Lutomirski
67e22438f8SAndy Lutomirski.size call32_from_64, .-call32_from_64
68