[haiku-commits] BRANCH xyzzy-github.x86_64 - src/system/libroot/os/arch/x86_64 src/system/kernel/arch/x86 headers/private/kernel/arch/x86

  • From: xyzzy-github.x86_64 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 8 Jul 2012 11:49:14 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64'
old head: 7444a55ce55af4fecf298a1749c1c23228305385
new head: 5c7d52183c2182761151ba2f8f72bb7b39e50053

----------------------------------------------------------------------------

5c7d521: Implemented system_time() for x86_64.
  
  * Uses 64-bit multiplication, special handling for CPUs clocked < 1 GHz
    in system_time_nsecs() not required like on x86.
  * Tested against a straight conversion of the x86 version, noticably
    faster with a large number of system_time() calls.

                                      [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      5c7d52183c2182761151ba2f8f72bb7b39e50053

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Sun Jul  8 09:16:44 2012 UTC

----------------------------------------------------------------------------

3 files changed, 47 insertions(+), 113 deletions(-)
headers/private/kernel/arch/x86/arch_cpu.h         |    7 +-
src/system/kernel/arch/x86/arch_cpu.cpp            |    7 +
.../libroot/os/arch/x86_64/system_time_asm.S       |  146 ++++------------

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/arch_cpu.h 
b/headers/private/kernel/arch/x86/arch_cpu.h
index f688a20..204c901 100644
--- a/headers/private/kernel/arch/x86/arch_cpu.h
+++ b/headers/private/kernel/arch/x86/arch_cpu.h
@@ -367,9 +367,14 @@ extern "C" {
 
 struct arch_thread;
 
-
+#ifdef __x86_64__
+void __x86_setup_system_time(uint64 conversionFactor,
+       uint64 conversionFactorNsecs);
+#else
 void __x86_setup_system_time(uint32 conversionFactor,
        uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
+#endif
+
 void x86_context_switch(struct arch_thread* oldState,
        struct arch_thread* newState);
 void x86_userspace_thread_exit(void);
diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index a618504..6a7a206 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -820,6 +820,12 @@ arch_cpu_init(kernel_args* args)
        uint32 conversionFactor = args->arch_args.system_time_cv_factor;
        uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000;
 
+#ifdef __x86_64__
+       // The x86_64 system_time() implementation uses 64-bit multiplication 
and
+       // therefore shifting is not necessary for low frequencies (it's also 
not
+       // too likely that there'll be any x86_64 CPUs clocked under 1GHz).
+       __x86_setup_system_time(conversionFactor, conversionFactorNsecs);
+#else
        if (conversionFactorNsecs >> 32 != 0) {
                // the TSC frequency is < 1 GHz, which forces us to shift the 
factor
                __x86_setup_system_time(conversionFactor, conversionFactorNsecs 
>> 16,
@@ -828,6 +834,7 @@ arch_cpu_init(kernel_args* args)
                // the TSC frequency is >= 1 GHz
                __x86_setup_system_time(conversionFactor, 
conversionFactorNsecs, false);
        }
+#endif
 
        return B_OK;
 }
diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S 
b/src/system/libroot/os/arch/x86_64/system_time_asm.S
index d6df8fa..f63bdf3 100644
--- a/src/system/libroot/os/arch/x86_64/system_time_asm.S
+++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S
@@ -7,143 +7,65 @@
  * Distributed under the terms of the NewOS License.
  */
 
-#include <asm_defs.h>
-
-FUNCTION(__x86_setup_system_time):
-       ret
-FUNCTION_END(__x86_setup_system_time)
-
-// TODO: Implement these.
-
-/* int64 system_time(); */
-FUNCTION(system_time):
-       ud2a
-       ret
-FUNCTION_END(system_time)
 
+#include <asm_defs.h>
 
-/* int64 system_time_nsecs(); */
-FUNCTION(system_time_nsecs):
-       ud2a
-       ret
-FUNCTION_END(system_time_nsecs)
 
-#if 0
 /* saves the conversion factor needed for system_time */
-.lcomm cv_factor                               4
-.lcomm cv_factor_nsecs                 4
-.lcomm cv_factor_nsecs_shift   1
+.lcomm cv_factor                               8
+.lcomm cv_factor_nsecs                 8
 
 
 .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
+       movq    %rdi, cv_factor
+       movq    %rsi, cv_factor_nsecs
        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
+       movq    cv_factor, %rcx
 
-1:
-       /* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */
+       // Load 64-bit TSC into %eax (low), %edx (high).
+       rdtsc
 
-       pushl   %ebx
-       pushl   %ecx
-       pushl   %esi
-       movl    cv_factor_nsecs, %ebx
+       // Convert into a single 64-bit value.
+       shl             $32, %rdx
+       orq             %rdx, %rax
 
-       /* load 64-bit factor into %eax (low), %edx (high) */
-       rdtsc           /* time in %edx,%eax */
+       // Multiply by conversion factor, result in %rax (low), %rdx (high).
+       mulq    %rcx
 
-       /* save high half */
-       movl    %edx, %ecx
-
-       /* multiply low half by conversion factor */
-       mull    %ebx
+       // Shift the result right by 32 bits.
+       shr             $32, %rax
+       shl             $32, %rdx
+       orq             %rdx, %rax
+       ret
+FUNCTION_END(system_time)
 
-       /* 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
+/* int64 system_time_nsecs(); */
+FUNCTION(system_time_nsecs):
+       // Same algorithm as system_time(), just with a different factor.
+       movq    cv_factor_nsecs, %rcx
 
-       /* now compute  [%edx, %eax] + [%ecx], propagating carry */
-       xorl    %ebx, %ebx      /* need zero to propagate carry */
-       addl    %ecx, %eax
-       adc             %ebx, %edx
+       // Load 64-bit TSC into %eax (low), %edx (high).
+       rdtsc
 
-       /* shift the result left 16 bit */
-       shl             $16, %edx
-       movl    %eax, %ebx
-       shr             $16, %ebx
-       orw             %bx, %dx
-       shl             $16, %eax
+       // Convert into a single 64-bit value.
+       shl             $32, %rdx
+       orq             %rdx, %rax
 
-       /* add the high 16 bit of the low half of the low product */
-       shr             $16, %esi
-       orw             %si, %ax
+       // Multiply by conversion factor, result in %rax (low), %rdx (high).
+       mulq    %rcx
 
-       popl    %esi
-       popl    %ecx
-       popl    %ebx
+       // Shift the result right by 32 bits.
+       shr             $32, %rax
+       shl             $32, %rdx
+       orq             %rdx, %rax
        ret
 FUNCTION_END(system_time_nsecs)
-#endif


Other related posts: