1/*
2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <sys/appleapiopts.h>
30#include <machine/cpu_capabilities.h>
31#include <machine/commpage.h>
32
33#define NSEC_PER_SEC	1000*1000*1000
34#define NSEC_PER_USEC	1000
35
36        .text
37        .align  2, 0x90
38
39Lgettimeofday:
40	push	%ebp
41	mov	%esp,%ebp
42	push	%esi
43	push	%ebx
44
450:
46	movl	_COMM_PAGE_GTOD_GENERATION,%esi	/* get generation (0 if disabled) */
47	testl	%esi,%esi			/* disabled? */
48	jz	4f
49
50	mov	$ _COMM_PAGE_NANOTIME,%eax
51	call	*%eax				/* get ns in %edx:%eax */
52
53
54	sub	_COMM_PAGE_GTOD_NS_BASE,%eax
55	sbb	_COMM_PAGE_GTOD_NS_BASE+4,%edx
56	mov	_COMM_PAGE_GTOD_SEC_BASE,%ebx	/* load all the data before checking generation */
57	mov	$ NSEC_PER_SEC,%ecx
58
59	cmpl	_COMM_PAGE_GTOD_GENERATION,%esi	/* has time data changed out from under us? */
60	jne	0b
61
62	div	%ecx
63	add	%eax,%ebx
64
65	mov	$ NSEC_PER_USEC,%ecx
66	mov	%edx,%eax
67	xor	%edx,%edx
68	div	%ecx
69
70	mov	8(%ebp),%ecx
71	mov	%ebx,(%ecx)
72	mov	%eax,4(%ecx)
73	xor	%eax,%eax
74
753:
76	pop	%ebx
77	pop	%esi
78	pop	%ebp
79	ret
804:				/* fail */
81	movl	$1,%eax
82	jmp	3b
83
84	COMMPAGE_DESCRIPTOR(gettimeofday,_COMM_PAGE_GETTIMEOFDAY,0,0)
85
86
87	.code64
88        .text
89        .align  2, 0x90
90
91Lgettimeofday_64:			// %rdi = ptr to timeval
92	pushq	%rbp			// set up a frame for backtraces
93	movq	%rsp,%rbp
94	movq	%rdi,%r9		// save ptr to timeval
95	movq	$_COMM_PAGE_32_TO_64(_COMM_PAGE_TIME_DATA_START),%r10
960:
97	movl	_GTOD_GENERATION(%r10),%r11d	// get generation (0 if disabled)
98	testl	%r11d,%r11d		// disabled?
99	jz	4f
100
101	movq	$_COMM_PAGE_32_TO_64(_COMM_PAGE_NANOTIME),%rax
102	call	*%rax			// get %rax <- nanotime(), preserving %r9, %r10 and %r11
103
104	movl	_GTOD_SEC_BASE(%r10),%r8d	// get _COMM_PAGE_TIMESTAMP
105	subq	_GTOD_NS_BASE(%r10),%rax	// generate nanoseconds since timestamp
106	cmpl	_GTOD_GENERATION(%r10),%r11d	// has data changed out from under us?
107	jne	0b
108
109	movl	$ NSEC_PER_SEC,%ecx
110	movq	%rax,%rdx
111	shrq	$32,%rdx		// get high half of delta in %edx
112	divl	%ecx			// %eax <- seconds since timestamp, %edx <- nanoseconds
113	addl	%eax,%r8d		// add seconds elapsed to timestamp seconds
114
115	movl	$ NSEC_PER_USEC,%ecx
116	movl	%edx,%eax
117	xorl	%edx,%edx
118	divl	%ecx			// divide residual ns by 1000 to get residual us in %eax
119
120	movq	%r8,(%r9)		// store 64-bit seconds into timeval
121	movl	%eax,8(%r9)		// store 32-bit useconds into timeval
122	xorl	%eax,%eax		// return 0 for success
1233:
124	popq	%rbp
125	ret
1264:					// fail
127	movl	$1,%eax
128	jmp	3b
129
130	COMMPAGE_DESCRIPTOR(gettimeofday_64,_COMM_PAGE_GETTIMEOFDAY,0,0)
131