weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr0_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr0_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr2_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr2_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr3_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr3_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr4_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr4_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_4Lidt_Rv_P2yt:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Ltr_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_9set_Mxcsr_Rv_P1j:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_9get_Mxcsr_Rj_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_6_Cpuid_Rv_P2jPj:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_RBP_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_RSP_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_5RdMsr_Ry_P1j:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Tsc_Ry_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Sti_Rv_P0:function
weak _ZX16MemoryOperationsM_0_19QuickClearAligned16_Rv_P2yy:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Cli_Rv_P0:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_RBP_Rv_P1y:function
weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Int_Rv_P1h:function

weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_5Break_Rv_P0:function

weak _ZW6System4MathM_0_5Round_Rd_P1d:function
weak _ZW6System4MathM_0_5Floor_Rd_P1d:function

weak _ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_6Invlpg_Rv_P1y:function

weak __memcpy:function
weak __memmove:function
weak __memset:function
weak __memsetw:function
weak __memcmp:function

weak _conv_u8_r8:function

extern __display_halt
extern __undefined_func

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr3_Ry_P0:
	mov	rax, cr3
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr3_Rv_P1y:
	mov rax, [rsp + 8]
	mov cr3, rax
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr0_Ry_P0:
	mov	rax, cr0
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr0_Rv_P1y:
	mov rax, [rsp + 8]
	mov cr0, rax
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr2_Ry_P0:
	mov	rax, cr2
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr2_Rv_P1y:
	mov rax, [rsp + 8]
	mov cr2, rax
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Cr4_Ry_P0:
	mov	rax, cr4
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_Cr4_Rv_P1y:
	mov rax, [rsp + 8]
	mov cr4, rax
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_4Lidt_Rv_P2yt:
	push rbp
	mov rbp, rsp

	sub rsp, 0x10
	
	mov rax, [rbp + 16]
	mov rbx, rax

	shr rbx, 48
	shl rax, 16
	add rax, [rbp + 24]

	mov [rsp], rax
	mov [rsp + 8], rbx

	lidt [rsp]

	leave
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Ltr_Rv_P1y:
	ltr [rsp + 8]
	ret

_ZX16MemoryOperationsM_0_19QuickClearAligned16_Rv_P2yy:
	push rbp
	mov rbp, rsp

	mov	rdi, [rbp + 16]
	mov rcx, [rbp + 24]

	shr rcx, 4

	sub rsp, 16
	mov rax, 0x0
	mov [rsp], rax
	mov [rsp + 8], rax

	movdqu	xmm0, [rsp]

.doloop:
	movdqa	[rdi], xmm0
	add	rdi, 16
	loop .doloop
	
	leave
	ret
	
__memcpy:
	push rbp
	mov rbp, rsp

	push 0 ; methodinfo

	mov rdi, [rbp + 16]
	mov rsi, [rbp + 24]
	mov ecx, [rbp + 32]

	rep movsb

	leave
	ret

__memset:
	push rbp
	mov rbp, rsp

	push 0 ; methodinfo

	mov rdi, [rbp + 16]
	mov eax, [rbp + 24]
	mov ecx, [rbp + 32]

	rep stosb

	leave
	ret

__memsetw:
	push rbp
	mov rbp, rsp

	push 0 ; methodinfo

	mov rdi, [rbp + 16]
	mov eax, [rbp + 24]
	mov ecx, [rbp + 32]

	rep stosw

	leave
	ret

__memcmp:
	push rbp
	mov rbp, rsp

	push 0 ; methodinfo

	mov rdi, [rbp + 16]
	mov rsi, [rbp + 24]
	mov ecx, [rbp + 32]
	xor eax, eax

.doloop:
	mov byte al, [rdi]
	sub byte al, [rsi]
	jnz .different
	inc rdi
	inc rsi
	loop .doloop

.different	
	leave
	ret

__memmove:
	push rbp
	mov rbp, rsp

	push 0 ; methodinfo

	mov rdi, [rbp + 16]
	mov rsi, [rbp + 24]
	mov ecx, [rbp + 32]
	
	cmp rdi, rsi
	ja .domove

	rep movsb
	leave
	ret

.domove:
	add rdi, rcx
	add rsi, rcx

	cmp rcx, 0
	jne .doloop

	leave
	ret

.doloop:
	dec rdi
	dec rsi
	
	mov byte al, [rsi]
	mov byte [rdi], al
	loop .doloop

	leave
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_RBP_Ry_P0:
	mov rax, rbp
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_RSP_Ry_P0:
	mov rax, rsp
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_9set_Mxcsr_Rv_P1j:
	ldmxcsr [rsp + 8]
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_9get_Mxcsr_Rj_P0:
	sub rsp, 8
	stmxcsr [rsp]
	mov dword eax, [rsp]
	add rsp, 8
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_6_Cpuid_Rv_P2jPj:
	; void _Cpuid(uint req_no, uint *buf)

	xor rcx, rcx
	mov dword eax, [rsp + 8]
	cpuid
	
	mov rdi, [rsp + 16]
	mov dword [rdi], eax
	mov dword [rdi + 4], ebx
	mov dword [rdi + 8], ecx
	mov dword [rdi + 12], edx

	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_5RdMsr_Ry_P1j:
	; static ulong RdMsr(uint reg_no)
	mov dword ecx, [rsp + 8]
	rdmsr
	sub rsp, 8
	mov dword [rsp], eax
	mov dword [rsp + 4], edx
	mov qword rax, [rsp]
	add rsp, 8
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7get_Tsc_Ry_P0:
	rdtsc
	sub rsp, 8
	mov dword [rsp], eax
	mov dword [rsp + 4], edx
	mov qword rax, [rsp]
	add rsp, 8
	ret

_conv_u8_r8:
	push qword [rsp]
	call __undefined_func
	call __display_halt
.haltloop:
	xchg bx, bx
	hlt
	jmp .haltloop

_ZW6System4MathM_0_5Round_Rd_P1d:
	; rely on the mxcsr rounding mode being round-to-even (set up in Arch)

	cvtsd2si	rax, [rsp + 8]
	cvtsi2sd	xmm0, rax

	ret

_ZW6System4MathM_0_5Floor_Rd_P1d:
	; set up rounding mode to floor (towards negative infinity)

	sub rsp, 8
	stmxcsr [rsp]
	mov eax, [rsp]
	mov ebx, eax

	; mask out then set rounding bits
	and eax, 0xffff9fff
	or eax, 0x2000

	; load mxcsr with the new value
	mov [rsp], eax
	ldmxcsr [rsp]

	; do the conversion
	cvtsd2si	rax, [rsp + 16]
	cvtsi2sd	xmm0, rax

	; restore mxcsr
	mov [rsp], ebx
	ldmxcsr [rsp]

	add rsp, 8

	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Sti_Rv_P0:
	sti
	ret
	
_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Cli_Rv_P0:
	cli
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_5Break_Rv_P0:
	int3
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_6Invlpg_Rv_P1y:
	mov rax, [rsp + 8]
	invlpg [rax]

	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_7set_RBP_Rv_P1y:
	mov rbp, [rsp + 8]
	ret

_ZN8libsupcs17libsupcs#2Ex86_643CpuM_0_3Int_Rv_P1h:
	mov rax, [rsp + 8]
	cmp rax, 256
	
	jae .invalid
	shl rax, 2
	mov rbx, .int_list
	add rax, rbx
	jmp rax

.invalid:
	ret
	
; a table containing int 0, ret, nop, int 1, ret, nop, int 2, ...
.int_list:
%assign i 0
%rep 256
	db 0xcd, i, 0xc3, 0x90
%assign i i+1
%endrep
.end_int_list:
