github.com/muyo/sno@v1.2.1/internal/time_windows_amd64.s (about)

     1  #include "textflag.h"
     2  #include "funcdata.h"
     3  
     4  // Uses the same approach as Go's runtime to get the current OS time as documented on:
     5  // https://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure
     6  // https://github.com/golang/go/blob/450d0b2f30e820f402a638799de0b886c1da8dbe/src/runtime/sys_windows_amd64.s#L499
     7  //
     8  // However, we skip a few things the runtime does to provide the facility to time.Now():
     9  // - There is no fallback to QPC, which means this won't work on Wine except the most recent versions;
    10  // - We offset the time straight into the sno epoch instead of into Unix first;
    11  // - We do not perform a unit conversion from 100nsec (as returned by the OS) into 1nsec. Instead we
    12  //   return this as is and the unit conversion is done in the wrapping snotime() function, where the
    13  //   division gets optimized by the compiler;
    14  // - There is no split into seconds and fractional nsecs, since - unlike time.Now() - this is the opposite
    15  //   of what we want;
    16  //
    17  // All in all this lets us shave off about a dozen instructions - including a fairly expensive back-and-forth
    18  // conversion between time units.
    19  //
    20  // func ostime() uint64
    21  TEXT ·ostime(SB), NOSPLIT, $0-8
    22      MOVQ $2147352596, DI    // 0x7ffe0014 -> 2147352596
    23  time:
    24      MOVL 4(DI), AX          // time_hi1
    25      MOVL 0(DI), BX          // time_lo
    26      MOVL 8(DI), CX          // time_hi2
    27      CMPL AX, CX
    28      JNE  time
    29  
    30      SHLQ $32, AX
    31      ORQ  BX, AX
    32  
    33      // Windows time as stored within _KUSER_SHARED_DATA starts at Jan 1st 1601.
    34      // The offset in the Windows units (100ns) to Unix epoch is a SUBQ by 116 444 736 000 000 000.
    35      //
    36      // Our internal epoch is:
    37      //          1 262 304 000    seconds on top of Unix.
    38      // 12 623 040 000 000 000‬    in units of 100nsec (secs * 1e7)
    39      //
    40      // As such we SUBQ 116444736000000000 (Windows to Unix diff) + 12623040000000000‬ (Sno to Unix diff)
    41      // 116 444 736 000 000 000
    42      //  12 623 040 000 000 000‬
    43      // ----
    44      // 129 067 776 000 000 000
    45  
    46      MOVQ $129067776000000000, DI
    47      SUBQ DI, AX
    48  
    49      MOVQ AX, ret+0(FP)
    50      RET