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
32#define NSEC_PER_SEC	1000*1000*1000
33#define NSEC_PER_USEC	1000
34
35#if defined(__i386__)
36
37	.align	4
38	.globl ___commpage_gettimeofday
39___commpage_gettimeofday:
40	push	%ebp
41	mov	%esp,%ebp
42	push	%esi
43	push	%ebx
440:
45	movl	_COMM_PAGE_GTOD_GENERATION,%esi	/* get generation (0 if disabled) */
46	testl	%esi,%esi			/* disabled? */
47	jz	4f
48
49	call	_mach_absolute_time		/* get nanotime in %edx:%eax */
50
51	sub	_COMM_PAGE_GTOD_NS_BASE,%eax
52	sbb	_COMM_PAGE_GTOD_NS_BASE+4,%edx
53	mov	_COMM_PAGE_GTOD_SEC_BASE,%ebx	/* load all the data before checking generation */
54	mov	$ NSEC_PER_SEC,%ecx
55
56	cmpl	_COMM_PAGE_GTOD_GENERATION,%esi	/* has time data changed out from under us? */
57	jne	0b
58
59	div	%ecx
60	add	%eax,%ebx
61
62	mov	$ NSEC_PER_USEC,%ecx
63	mov	%edx,%eax
64	xor	%edx,%edx
65	div	%ecx
66
67	mov	8(%ebp),%ecx
68	mov	%ebx,(%ecx)
69	mov	%eax,4(%ecx)
70	xor	%eax,%eax
713:
72	pop	%ebx
73	pop	%esi
74	pop	%ebp
75	ret
764:				/* fail */
77	movl	$1,%eax
78	jmp	3b
79
80#elif defined(__x86_64__)
81
82	.align 4, 0x90
83	.globl ___commpage_gettimeofday
84___commpage_gettimeofday:
85// %rdi = ptr to timeval
86	pushq	%rbp			// set up a frame for backtraces
87	pushq	%r12			// push callee-saved registers we want to use
88	pushq	%r13
89	pushq	%r14
90	subq	$8, %rsp
91	movq	%rsp,%rbp
92	movq	%rdi,%r12		// save ptr to timeval
93	movq	$(_COMM_PAGE_TIME_DATA_START),%r13
940:
95	movl	_GTOD_GENERATION(%r13),%r14d	// get generation (0 if disabled)
96	testl	%r14d,%r14d		// disabled?
97	jz	4f
98
99	call	_mach_absolute_time	// get %rax <- nanotime()
100
101	movl	_GTOD_SEC_BASE(%r13),%r8d	// get _COMM_PAGE_TIMESTAMP
102	subq	_GTOD_NS_BASE(%r13),%rax	// generate nanoseconds since timestamp
103	cmpl	_GTOD_GENERATION(%r13),%r14d	// has data changed out from under us?
104	jne	0b
105
106	movl	$ NSEC_PER_SEC,%ecx
107	movq	%rax,%rdx
108	shrq	$32,%rdx		// get high half of delta in %edx
109	divl	%ecx			// %eax <- seconds since timestamp, %edx <- nanoseconds
110	addl	%eax,%r8d		// add seconds elapsed to timestamp seconds
111
112	movl	$ NSEC_PER_USEC,%ecx
113	movl	%edx,%eax
114	xorl	%edx,%edx
115	divl	%ecx			// divide residual ns by 1000 to get residual us in %eax
116
117	movq	%r8,(%r12)		// store 64-bit seconds into timeval
118	movl	%eax,8(%r12)		// store 32-bit useconds into timeval
119	xorl	%eax,%eax		// return 0 for success
1203:
121	addq	$8, %rsp
122	popq	%r14
123	popq	%r13
124	popq	%r12
125	popq	%rbp
126	ret
1274:					// fail
128	movl	$1,%eax
129	jmp	3b
130
131#endif
132