summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64/regs.c
blob: bb4e5aae1a86ac0d45ac2b82a19a3c8457f45a78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <kernel/arch/generic.h>
#include <kernel/panic.h>

void
regs_safecopy(UserRegs *dst, const UserRegs *src)
{
	/* preserved flags: (see intel vol 1 3.4.3.)
	 * 1<<0 = CF, carry flag
	 * 1<<2 = PF, parity flag
	 * 1<<4 = AC, auxilary carry
	 * 1<<6 = ZF, zero flag
	 * 1<<7 = SF, sign flag
	 * 1<<11 = OF, overflow flag
	 * 1<<10 = DF, direction flag
	 */
	static_assert(
		((1<<0) | (1<<2) | (1<<4) | (1<<6) | (1<<7) | (1<<10) | (1<<11))
		== 0xCD5
	);

	uint64_t newflags = (src->flags & 0xCD5) | (dst->flags & ~0xCD5);
	/* I "spelled it out" directly instead of using memcpy hoping that gcc
	 * maybe would notice it can skip copying the last 8 bytes. It didn't :( */
	*dst = *src;
	dst->flags = newflags;
}