162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/linkage.h>
462306a36Sopenharmony_ci#include <asm/export.h>
562306a36Sopenharmony_ci#include <asm/percpu.h>
662306a36Sopenharmony_ci#include <asm/processor-flags.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci.text
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef CONFIG_X86_CMPXCHG64
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * Emulate 'cmpxchg8b (%esi)' on UP
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Inputs:
1662306a36Sopenharmony_ci * %esi : memory location to compare
1762306a36Sopenharmony_ci * %eax : low 32 bits of old value
1862306a36Sopenharmony_ci * %edx : high 32 bits of old value
1962306a36Sopenharmony_ci * %ebx : low 32 bits of new value
2062306a36Sopenharmony_ci * %ecx : high 32 bits of new value
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ciSYM_FUNC_START(cmpxchg8b_emu)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	pushfl
2562306a36Sopenharmony_ci	cli
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	cmpl	0(%esi), %eax
2862306a36Sopenharmony_ci	jne	.Lnot_same
2962306a36Sopenharmony_ci	cmpl	4(%esi), %edx
3062306a36Sopenharmony_ci	jne	.Lnot_same
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	movl	%ebx, 0(%esi)
3362306a36Sopenharmony_ci	movl	%ecx, 4(%esi)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	orl	$X86_EFLAGS_ZF, (%esp)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	popfl
3862306a36Sopenharmony_ci	RET
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci.Lnot_same:
4162306a36Sopenharmony_ci	movl	0(%esi), %eax
4262306a36Sopenharmony_ci	movl	4(%esi), %edx
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	andl	$(~X86_EFLAGS_ZF), (%esp)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	popfl
4762306a36Sopenharmony_ci	RET
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciSYM_FUNC_END(cmpxchg8b_emu)
5062306a36Sopenharmony_ciEXPORT_SYMBOL(cmpxchg8b_emu)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#endif
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#ifndef CONFIG_UML
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciSYM_FUNC_START(this_cpu_cmpxchg8b_emu)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	pushfl
5962306a36Sopenharmony_ci	cli
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	cmpl	PER_CPU_VAR(0(%esi)), %eax
6262306a36Sopenharmony_ci	jne	.Lnot_same2
6362306a36Sopenharmony_ci	cmpl	PER_CPU_VAR(4(%esi)), %edx
6462306a36Sopenharmony_ci	jne	.Lnot_same2
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	movl	%ebx, PER_CPU_VAR(0(%esi))
6762306a36Sopenharmony_ci	movl	%ecx, PER_CPU_VAR(4(%esi))
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	orl	$X86_EFLAGS_ZF, (%esp)
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	popfl
7262306a36Sopenharmony_ci	RET
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci.Lnot_same2:
7562306a36Sopenharmony_ci	movl	PER_CPU_VAR(0(%esi)), %eax
7662306a36Sopenharmony_ci	movl	PER_CPU_VAR(4(%esi)), %edx
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	andl	$(~X86_EFLAGS_ZF), (%esp)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	popfl
8162306a36Sopenharmony_ci	RET
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciSYM_FUNC_END(this_cpu_cmpxchg8b_emu)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#endif
86