162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * thunks_32.S - assembly helpers for mixed-bitness code
462306a36Sopenharmony_ci * Copyright (c) 2015 Denys Vlasenko
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * These are little helpers that make it easier to switch bitness on
762306a36Sopenharmony_ci * the fly.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci	.text
1162306a36Sopenharmony_ci	.code32
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	.global call64_from_32
1462306a36Sopenharmony_ci	.type call32_from_64, @function
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	// 4(%esp): function to call
1762306a36Sopenharmony_cicall64_from_32:
1862306a36Sopenharmony_ci	// Fetch function address
1962306a36Sopenharmony_ci	mov	4(%esp), %eax
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	// Save registers which are callee-clobbered by 64-bit ABI
2262306a36Sopenharmony_ci	push	%ecx
2362306a36Sopenharmony_ci	push	%edx
2462306a36Sopenharmony_ci	push	%esi
2562306a36Sopenharmony_ci	push	%edi
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	// Switch to long mode
2862306a36Sopenharmony_ci	jmp	$0x33,$1f
2962306a36Sopenharmony_ci1:	.code64
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	// Call the function
3262306a36Sopenharmony_ci	call	*%rax
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	// Switch to compatibility mode
3562306a36Sopenharmony_ci	push	$0x23  /* USER32_CS */
3662306a36Sopenharmony_ci	.code32; push $1f; .code64 /* hack: can't have X86_64_32S relocation in 32-bit ELF */
3762306a36Sopenharmony_ci	lretq
3862306a36Sopenharmony_ci1:	.code32
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	pop	%edi
4162306a36Sopenharmony_ci	pop	%esi
4262306a36Sopenharmony_ci	pop	%edx
4362306a36Sopenharmony_ci	pop	%ecx
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	ret
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci.size call64_from_32, .-call64_from_32
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci.section .note.GNU-stack,"",%progbits
50