// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !faketime
// +build !faketime

#include "go_asm.h"
#include "textflag.h"
#include "time_windows.h"

TEXT time·now(SB),NOSPLIT,$0-20
	CMPB	runtime·useQPCTime(SB), $0
	JNE	useQPC
loop:
	MOVL	(_INTERRUPT_TIME+time_hi1), AX
	MOVL	(_INTERRUPT_TIME+time_lo), CX
	MOVL	(_INTERRUPT_TIME+time_hi2), DI
	CMPL	AX, DI
	JNE	loop

	// w = DI:CX
	// multiply by 100
	MOVL	$100, AX
	MULL	CX
	IMULL	$100, DI
	ADDL	DI, DX
	// w*100 = DX:AX
	MOVL	AX, mono+12(FP)
	MOVL	DX, mono+16(FP)

wall:
	MOVL	(_SYSTEM_TIME+time_hi1), CX
	MOVL	(_SYSTEM_TIME+time_lo), AX
	MOVL	(_SYSTEM_TIME+time_hi2), DX
	CMPL	CX, DX
	JNE	wall

	// w = DX:AX
	// convert to Unix epoch (but still 100ns units)
	#define delta 116444736000000000
	SUBL	$(delta & 0xFFFFFFFF), AX
	SBBL $(delta >> 32), DX

	// nano/100 = DX:AX
	// split into two decimal halves by div 1e9.
	// (decimal point is two spots over from correct place,
	// but we avoid overflow in the high word.)
	MOVL	$1000000000, CX
	DIVL	CX
	MOVL	AX, DI
	MOVL	DX, SI

	// DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9
	// split DX into seconds and nanoseconds by div 1e7 magic multiply.
	MOVL	DX, AX
	MOVL	$1801439851, CX
	MULL	CX
	SHRL	$22, DX
	MOVL	DX, BX
	IMULL	$10000000, DX
	MOVL	SI, CX
	SUBL	DX, CX

	// DI = sec/100 (still)
	// BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100
	// CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100
	// store nsec for return
	IMULL	$100, CX
	MOVL	CX, nsec+8(FP)

	// DI = sec/100 (still)
	// BX = sec%100
	// construct DX:AX = 64-bit sec and store for return
	MOVL	$0, DX
	MOVL	$100, AX
	MULL	DI
	ADDL	BX, AX
	ADCL	$0, DX
	MOVL	AX, sec+0(FP)
	MOVL	DX, sec+4(FP)
	RET
useQPC:
	JMP	runtime·nowQPC(SB)
	RET
