/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include <asm_defs.h>
/* saves the conversion factor needed for system_time */
.lcomm cv_factor 4
.lcomm cv_factor_nsecs 4
.lcomm cv_factor_nsecs_shift 1
.text
FUNCTION(__x86_setup_system_time):
movl 4(%esp), %eax
movl %eax, cv_factor
movl 8(%esp), %eax
movl %eax, cv_factor_nsecs
movb 12(%esp), %al
movb %al, cv_factor_nsecs_shift
ret
FUNCTION_END(__x86_setup_system_time)
/* int64 system_time()
FUNCTION(system_time):
pushl %ebx
pushl %ecx
movl cv_factor, %ebx
/* load 64-bit factor into %eax (low), %edx (high) */
rdtsc /* time in %edx,%eax */
movl %edx, %ecx /* save high half */
mull %ebx /* truncate %eax, but keep %edx */
movl %ecx, %eax
movl %edx, %ecx /* save high half of low */
mull %ebx /*, %eax*/
/* now compute [%edx, %eax] + [%ecx], propagating carry */
subl %ebx, %ebx /* need zero to propagate carry */
addl %ecx, %eax
adc %ebx, %edx
popl %ecx
popl %ebx
ret
FUNCTION_END(system_time)
/* int64 system_time_nsecs()
FUNCTION(system_time_nsecs):
testb $0, cv_factor_nsecs_shift
jne 1f
/* same algorithm as system_time(), just with a different factor */
pushl %ebx
pushl %ecx
movl cv_factor_nsecs, %ebx
/* load 64-bit factor into %eax (low), %edx (high) */
rdtsc /* time in %edx,%eax */
movl %edx, %ecx /* save high half */
mull %ebx /* truncate %eax, but keep %edx */
movl %ecx, %eax
movl %edx, %ecx /* save high half of low */
mull %ebx /*, %eax*/
/* now compute [%edx, %eax] + [%ecx], propagating carry */
subl %ebx, %ebx /* need zero to propagate carry */
addl %ecx, %eax
adc %ebx, %edx
popl %ecx
popl %ebx
ret
1:
/* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */
pushl %ebx
pushl %ecx
pushl %esi
movl cv_factor_nsecs, %ebx
/* load 64-bit factor into %eax (low), %edx (high) */
rdtsc /* time in %edx,%eax */
/* save high half */
movl %edx, %ecx
/* multiply low half by conversion factor */
mull %ebx
/* save result */
movl %eax, %esi /* low half -> %esi */
movl %ecx, %eax
movl %edx, %ecx /* high half -> %ecx */
/* multiply high half by conversion factor */
mull %ebx
/* now compute [%edx, %eax] + [%ecx], propagating carry */
xorl %ebx, %ebx /* need zero to propagate carry */
addl %ecx, %eax
adc %ebx, %edx
/* shift the result left 16 bit */
shl $16, %edx
movl %eax, %ebx
shr $16, %ebx
orw %bx, %dx
shl $16, %eax
/* add the high 16 bit of the low half of the low product */
shr $16, %esi
orw %si, %ax
popl %esi
popl %ecx
popl %ebx
ret
FUNCTION_END(system_time_nsecs)