~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/runtime/asm_amd64.s

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 
7
7
TEXT _rt0_amd64(SB),7,$-8
8
8
        // copy arguments forward on an even stack
9
 
        MOVQ    0(DI), AX               // argc
10
 
        LEAQ    8(DI), BX               // argv
 
9
        MOVQ    DI, AX          // argc
 
10
        MOVQ    SI, BX          // argv
11
11
        SUBQ    $(4*8+7), SP            // 2args 2auto
12
12
        ANDQ    $~15, SP
13
13
        MOVQ    AX, 16(SP)
14
14
        MOVQ    BX, 24(SP)
15
15
        
16
16
        // create istack out of the given (operating system) stack.
17
 
        // initcgo may update stackguard.
 
17
        // _cgo_init may update stackguard.
18
18
        MOVQ    $runtime·g0(SB), DI
19
19
        LEAQ    (-64*1024+104)(SP), BX
20
20
        MOVQ    BX, g_stackguard(DI)
21
21
        MOVQ    SP, g_stackbase(DI)
22
22
 
23
 
        // if there is an initcgo, call it.
24
 
        MOVQ    initcgo(SB), AX
 
23
        // find out information about the processor we're on
 
24
        MOVQ    $0, AX
 
25
        CPUID
 
26
        CMPQ    AX, $0
 
27
        JE      nocpuinfo
 
28
        MOVQ    $1, AX
 
29
        CPUID
 
30
        MOVL    CX, runtime·cpuid_ecx(SB)
 
31
        MOVL    DX, runtime·cpuid_edx(SB)
 
32
nocpuinfo:      
 
33
        
 
34
        // if there is an _cgo_init, call it.
 
35
        MOVQ    _cgo_init(SB), AX
25
36
        TESTQ   AX, AX
26
37
        JZ      needtls
27
38
        // g0 already in DI
28
39
        MOVQ    DI, CX  // Win64 uses CX for first parameter
 
40
        MOVQ    $setmg_gcc<>(SB), SI
29
41
        CALL    AX
30
42
        CMPL    runtime·iswindows(SB), $0
31
43
        JEQ ok
32
44
 
33
45
needtls:
 
46
        // skip TLS setup on Plan 9
 
47
        CMPL    runtime·isplan9(SB), $1
 
48
        JEQ ok
 
49
 
34
50
        LEAQ    runtime·tls0(SB), DI
35
51
        CALL    runtime·settls(SB)
36
52
 
61
77
        MOVQ    AX, 8(SP)
62
78
        CALL    runtime·args(SB)
63
79
        CALL    runtime·osinit(SB)
 
80
        CALL    runtime·hashinit(SB)
64
81
        CALL    runtime·schedinit(SB)
65
82
 
66
83
        // create a new goroutine to start program
67
 
        PUSHQ   $runtime·main(SB)               // entry
 
84
        PUSHQ   $runtime·main·f(SB)             // entry
68
85
        PUSHQ   $0                      // arg size
69
86
        CALL    runtime·newproc(SB)
70
87
        POPQ    AX
76
93
        MOVL    $0xf1, 0xf1  // crash
77
94
        RET
78
95
 
 
96
DATA    runtime·main·f+0(SB)/8,$runtime·main(SB)
 
97
GLOBL   runtime·main·f(SB),8,$8
 
98
 
79
99
TEXT runtime·breakpoint(SB),7,$0
80
100
        BYTE    $0xcc
81
101
        RET
114
134
        MOVQ    gobuf_pc(BX), BX
115
135
        JMP     BX
116
136
 
117
 
// void gogocall(Gobuf*, void (*fn)(void))
 
137
// void gogocall(Gobuf*, void (*fn)(void), uintptr r0)
118
138
// restore state from Gobuf but then call fn.
119
139
// (call fn, returning to state in Gobuf)
120
140
TEXT runtime·gogocall(SB), 7, $0
 
141
        MOVQ    24(SP), DX      // context
121
142
        MOVQ    16(SP), AX              // fn
122
143
        MOVQ    8(SP), BX               // gobuf
123
 
        MOVQ    gobuf_g(BX), DX
 
144
        MOVQ    gobuf_g(BX), DI
124
145
        get_tls(CX)
125
 
        MOVQ    DX, g(CX)
126
 
        MOVQ    0(DX), CX       // make sure g != nil
 
146
        MOVQ    DI, g(CX)
 
147
        MOVQ    0(DI), CX       // make sure g != nil
127
148
        MOVQ    gobuf_sp(BX), SP        // restore SP
128
149
        MOVQ    gobuf_pc(BX), BX
129
150
        PUSHQ   BX
130
151
        JMP     AX
131
152
        POPQ    BX      // not reached
132
153
 
 
154
// void gogocallfn(Gobuf*, FuncVal*)
 
155
// restore state from Gobuf but then call fn.
 
156
// (call fn, returning to state in Gobuf)
 
157
TEXT runtime·gogocallfn(SB), 7, $0
 
158
        MOVQ    16(SP), DX              // fn
 
159
        MOVQ    8(SP), BX               // gobuf
 
160
        MOVQ    gobuf_g(BX), AX
 
161
        get_tls(CX)
 
162
        MOVQ    AX, g(CX)
 
163
        MOVQ    0(AX), CX       // make sure g != nil
 
164
        MOVQ    gobuf_sp(BX), SP        // restore SP
 
165
        MOVQ    gobuf_pc(BX), BX
 
166
        PUSHQ   BX
 
167
        MOVQ    0(DX), BX
 
168
        JMP     BX
 
169
        POPQ    BX      // not reached
 
170
 
133
171
// void mcall(void (*fn)(G*))
134
172
// Switch to m->g0's stack, call fn(g).
135
173
// Fn must never return.  It should gogo(&g->sched)
171
209
        CMPQ    g(CX), SI
172
210
        JNE     2(PC)
173
211
        INT     $3
 
212
        
 
213
        MOVQ    DX, m_cret(BX)
174
214
 
175
215
        // Called from f.
176
216
        // Set m->morebuf to f's caller.
344
384
        MOVL    $1, AX
345
385
        RET
346
386
 
 
387
// bool runtime·cas64(uint64 *val, uint64 *old, uint64 new)
 
388
// Atomically:
 
389
//      if(*val == *old){
 
390
//              *val = new;
 
391
//              return 1;
 
392
//      } else {
 
393
//              *old = *val
 
394
//              return 0;
 
395
//      }
 
396
TEXT runtime·cas64(SB), 7, $0
 
397
        MOVQ    8(SP), BX
 
398
        MOVQ    16(SP), BP
 
399
        MOVQ    0(BP), AX
 
400
        MOVQ    24(SP), CX
 
401
        LOCK
 
402
        CMPXCHGQ        CX, 0(BX)
 
403
        JNZ     cas64_fail
 
404
        MOVL    $1, AX
 
405
        RET
 
406
cas64_fail:
 
407
        MOVQ    AX, 0(BP)
 
408
        MOVL    $0, AX
 
409
        RET
 
410
 
347
411
// bool casp(void **val, void *old, void *new)
348
412
// Atomically:
349
413
//      if(*val == old){
376
440
        ADDL    CX, AX
377
441
        RET
378
442
 
 
443
TEXT runtime·xadd64(SB), 7, $0
 
444
        MOVQ    8(SP), BX
 
445
        MOVQ    16(SP), AX
 
446
        MOVQ    AX, CX
 
447
        LOCK
 
448
        XADDQ   AX, 0(BX)
 
449
        ADDQ    CX, AX
 
450
        RET
 
451
 
379
452
TEXT runtime·xchg(SB), 7, $0
380
453
        MOVQ    8(SP), BX
381
454
        MOVL    16(SP), AX
382
455
        XCHGL   AX, 0(BX)
383
456
        RET
384
457
 
 
458
TEXT runtime·xchg64(SB), 7, $0
 
459
        MOVQ    8(SP), BX
 
460
        MOVQ    16(SP), AX
 
461
        XCHGQ   AX, 0(BX)
 
462
        RET
 
463
 
385
464
TEXT runtime·procyield(SB),7,$0
386
465
        MOVL    8(SP), AX
387
466
again:
402
481
        XCHGL   AX, 0(BX)
403
482
        RET
404
483
 
 
484
TEXT runtime·atomicstore64(SB), 7, $0
 
485
        MOVQ    8(SP), BX
 
486
        MOVQ    16(SP), AX
 
487
        XCHGQ   AX, 0(BX)
 
488
        RET
 
489
 
405
490
// void jmpdefer(fn, sp);
406
491
// called from deferreturn.
407
492
// 1. pop the caller
408
493
// 2. sub 5 bytes from the callers return
409
494
// 3. jmp to the argument
410
495
TEXT runtime·jmpdefer(SB), 7, $0
411
 
        MOVQ    8(SP), AX       // fn
 
496
        MOVQ    8(SP), DX       // fn
412
497
        MOVQ    16(SP), BX      // caller sp
413
498
        LEAQ    -8(BX), SP      // caller sp after CALL
414
499
        SUBQ    $5, (SP)        // return to CALL again
415
 
        JMP     AX      // but first run the deferred function
 
500
        MOVQ    0(DX), BX
 
501
        JMP     BX      // but first run the deferred function
416
502
 
417
503
// Dummy function to use in saved gobuf.PC,
418
504
// to match SP pointing at a return address.
446
532
        MOVQ    (g_sched+gobuf_sp)(SI), SP
447
533
 
448
534
        // Now on a scheduling stack (a pthread-created stack).
449
 
        SUBQ    $48, SP
 
535
        // Make sure we have enough room for 4 stack-backed fast-call
 
536
        // registers as per windows amd64 calling convention.
 
537
        SUBQ    $64, SP
450
538
        ANDQ    $~15, SP        // alignment for gcc ABI
451
 
        MOVQ    DI, 32(SP)      // save g
452
 
        MOVQ    DX, 24(SP)      // save SP
 
539
        MOVQ    DI, 48(SP)      // save g
 
540
        MOVQ    DX, 40(SP)      // save SP
453
541
        MOVQ    BX, DI          // DI = first argument in AMD64 ABI
454
542
        MOVQ    BX, CX          // CX = first argument in Win64
455
543
        CALL    AX
456
544
 
457
545
        // Restore registers, g, stack pointer.
458
546
        get_tls(CX)
459
 
        MOVQ    32(SP), DI
 
547
        MOVQ    48(SP), DI
460
548
        MOVQ    DI, g(CX)
461
 
        MOVQ    24(SP), SP
 
549
        MOVQ    40(SP), SP
462
550
        RET
463
551
 
464
552
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
465
 
// See cgocall.c for more details.
 
553
// Turn the fn into a Go func (by taking its address) and call
 
554
// cgocallback_gofunc.
466
555
TEXT runtime·cgocallback(SB),7,$24
467
 
        MOVQ    fn+0(FP), AX
468
 
        MOVQ    frame+8(FP), BX
469
 
        MOVQ    framesize+16(FP), DX
470
 
 
 
556
        LEAQ    fn+0(FP), AX
 
557
        MOVQ    AX, 0(SP)
 
558
        MOVQ    frame+8(FP), AX
 
559
        MOVQ    AX, 8(SP)
 
560
        MOVQ    framesize+16(FP), AX
 
561
        MOVQ    AX, 16(SP)
 
562
        MOVQ    $runtime·cgocallback_gofunc(SB), AX
 
563
        CALL    AX
 
564
        RET
 
565
 
 
566
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
 
567
// See cgocall.c for more details.
 
568
TEXT runtime·cgocallback_gofunc(SB),7,$24
 
569
        // If m is nil, Go did not create the current thread.
 
570
        // Call needm to obtain one for temporary use.
 
571
        // In this case, we're running on the thread stack, so there's
 
572
        // lots of space, but the linker doesn't know. Hide the call from
 
573
        // the linker analysis by using an indirect call through AX.
 
574
        get_tls(CX)
 
575
#ifdef GOOS_windows
 
576
        CMPQ    CX, $0
 
577
        JNE     3(PC)
 
578
        PUSHQ   $0
 
579
        JMP     needm
 
580
#endif
 
581
        MOVQ    m(CX), BP
 
582
        PUSHQ   BP
 
583
        CMPQ    BP, $0
 
584
        JNE     havem
 
585
needm:
 
586
        MOVQ    $runtime·needm(SB), AX
 
587
        CALL    AX
 
588
        get_tls(CX)
 
589
        MOVQ    m(CX), BP
 
590
 
 
591
havem:
 
592
        // Now there's a valid m, and we're running on its m->g0.
471
593
        // Save current m->g0->sched.sp on stack and then set it to SP.
472
 
        get_tls(CX)
473
 
        MOVQ    m(CX), BP
474
 
        
475
 
        // If m is nil, it is almost certainly because we have been called
476
 
        // on a thread that Go did not create.  We're going to crash as
477
 
        // soon as we try to use m; instead, try to print a nice error and exit.
478
 
        CMPQ    BP, $0
479
 
        JNE 2(PC)
480
 
        CALL    runtime·badcallback(SB)
481
 
 
 
594
        // Save current sp in m->g0->sched.sp in preparation for
 
595
        // switch back to m->curg stack.
482
596
        MOVQ    m_g0(BP), SI
483
597
        PUSHQ   (g_sched+gobuf_sp)(SI)
484
598
        MOVQ    SP, (g_sched+gobuf_sp)(SI)
497
611
        // a frame size of 24, the same amount that we use below),
498
612
        // so that the traceback will seamlessly trace back into
499
613
        // the earlier calls.
 
614
        MOVQ    fn+0(FP), AX
 
615
        MOVQ    frame+8(FP), BX
 
616
        MOVQ    framesize+16(FP), DX
 
617
 
500
618
        MOVQ    m_curg(BP), SI
501
619
        MOVQ    SI, g(CX)
502
620
        MOVQ    (g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
534
652
        MOVQ    SI, g(CX)
535
653
        MOVQ    (g_sched+gobuf_sp)(SI), SP
536
654
        POPQ    (g_sched+gobuf_sp)(SI)
 
655
        
 
656
        // If the m on entry was nil, we called needm above to borrow an m
 
657
        // for the duration of the call. Since the call is over, return it with dropm.
 
658
        POPQ    BP
 
659
        CMPQ    BP, $0
 
660
        JNE 3(PC)
 
661
        MOVQ    $runtime·dropm(SB), AX
 
662
        CALL    AX
537
663
 
538
664
        // Done!
539
665
        RET
540
666
 
 
667
// void setmg(M*, G*); set m and g. for use by needm.
 
668
TEXT runtime·setmg(SB), 7, $0
 
669
        MOVQ    mm+0(FP), AX
 
670
#ifdef GOOS_windows
 
671
        CMPQ    AX, $0
 
672
        JNE     settls
 
673
        MOVQ    $0, 0x28(GS)
 
674
        RET
 
675
settls:
 
676
        LEAQ    m_tls(AX), AX
 
677
        MOVQ    AX, 0x28(GS)
 
678
#endif
 
679
        get_tls(CX)
 
680
        MOVQ    mm+0(FP), AX
 
681
        MOVQ    AX, m(CX)
 
682
        MOVQ    gg+8(FP), BX
 
683
        MOVQ    BX, g(CX)
 
684
        RET
 
685
 
 
686
// void setmg_gcc(M*, G*); set m and g called from gcc.
 
687
TEXT setmg_gcc<>(SB),7,$0
 
688
        get_tls(AX)
 
689
        MOVQ    DI, m(AX)
 
690
        MOVQ    SI, g(AX)
 
691
        RET
 
692
 
541
693
// check that SP is in range [g->stackbase, g->stackguard)
542
694
TEXT runtime·stackcheck(SB), 7, $0
543
695
        get_tls(CX)
593
745
        get_tls(CX)
594
746
        MOVQ    g(CX), BX
595
747
        MOVQ    g_stackguard(BX), DX
596
 
        MOVQ    DX, guard+8(FP)
 
748
        MOVQ    DX, limit+8(FP)
597
749
        RET
598
750
 
599
751
GLOBL runtime·tls0(SB), $64
 
752
 
 
753
// hash function using AES hardware instructions
 
754
TEXT runtime·aeshash(SB),7,$0
 
755
        MOVQ    8(SP), DX       // ptr to hash value
 
756
        MOVQ    16(SP), CX      // size
 
757
        MOVQ    24(SP), AX      // ptr to data
 
758
        JMP     runtime·aeshashbody(SB)
 
759
 
 
760
TEXT runtime·aeshashstr(SB),7,$0
 
761
        MOVQ    8(SP), DX       // ptr to hash value
 
762
        MOVQ    24(SP), AX      // ptr to string struct
 
763
        MOVQ    8(AX), CX       // length of string
 
764
        MOVQ    (AX), AX        // string data
 
765
        JMP     runtime·aeshashbody(SB)
 
766
 
 
767
// AX: data
 
768
// CX: length
 
769
// DX: ptr to seed input / hash output
 
770
TEXT runtime·aeshashbody(SB),7,$0
 
771
        MOVQ    (DX), X0        // seed to low 64 bits of xmm0
 
772
        PINSRQ  $1, CX, X0      // size to high 64 bits of xmm0
 
773
        MOVO    runtime·aeskeysched+0(SB), X2
 
774
        MOVO    runtime·aeskeysched+16(SB), X3
 
775
aesloop:
 
776
        CMPQ    CX, $16
 
777
        JB      aesloopend
 
778
        MOVOU   (AX), X1
 
779
        AESENC  X2, X0
 
780
        AESENC  X1, X0
 
781
        SUBQ    $16, CX
 
782
        ADDQ    $16, AX
 
783
        JMP     aesloop
 
784
aesloopend:
 
785
        TESTQ   CX, CX
 
786
        JE      finalize        // no partial block
 
787
 
 
788
        TESTQ   $16, AX
 
789
        JNE     highpartial
 
790
 
 
791
        // address ends in 0xxxx.  16 bytes loaded
 
792
        // at this address won't cross a page boundary, so
 
793
        // we can load it directly.
 
794
        MOVOU   (AX), X1
 
795
        ADDQ    CX, CX
 
796
        PAND    masks(SB)(CX*8), X1
 
797
        JMP     partial
 
798
highpartial:
 
799
        // address ends in 1xxxx.  Might be up against
 
800
        // a page boundary, so load ending at last byte.
 
801
        // Then shift bytes down using pshufb.
 
802
        MOVOU   -16(AX)(CX*1), X1
 
803
        ADDQ    CX, CX
 
804
        PSHUFB  shifts(SB)(CX*8), X1
 
805
partial:
 
806
        // incorporate partial block into hash
 
807
        AESENC  X3, X0
 
808
        AESENC  X1, X0
 
809
finalize:       
 
810
        // finalize hash
 
811
        AESENC  X2, X0
 
812
        AESENC  X3, X0
 
813
        AESENC  X2, X0
 
814
        MOVQ    X0, (DX)
 
815
        RET
 
816
 
 
817
TEXT runtime·aeshash32(SB),7,$0
 
818
        MOVQ    8(SP), DX       // ptr to hash value
 
819
        MOVQ    24(SP), AX      // ptr to data
 
820
        MOVQ    (DX), X0        // seed
 
821
        PINSRD  $2, (AX), X0    // data
 
822
        AESENC  runtime·aeskeysched+0(SB), X0
 
823
        AESENC  runtime·aeskeysched+16(SB), X0
 
824
        AESENC  runtime·aeskeysched+0(SB), X0
 
825
        MOVQ    X0, (DX)
 
826
        RET
 
827
 
 
828
TEXT runtime·aeshash64(SB),7,$0
 
829
        MOVQ    8(SP), DX       // ptr to hash value
 
830
        MOVQ    24(SP), AX      // ptr to data
 
831
        MOVQ    (DX), X0        // seed
 
832
        PINSRQ  $1, (AX), X0    // data
 
833
        AESENC  runtime·aeskeysched+0(SB), X0
 
834
        AESENC  runtime·aeskeysched+16(SB), X0
 
835
        AESENC  runtime·aeskeysched+0(SB), X0
 
836
        MOVQ    X0, (DX)
 
837
        RET
 
838
 
 
839
// simple mask to get rid of data in the high part of the register.
 
840
TEXT masks(SB),7,$0
 
841
        QUAD $0x0000000000000000
 
842
        QUAD $0x0000000000000000
 
843
        QUAD $0x00000000000000ff
 
844
        QUAD $0x0000000000000000
 
845
        QUAD $0x000000000000ffff
 
846
        QUAD $0x0000000000000000
 
847
        QUAD $0x0000000000ffffff
 
848
        QUAD $0x0000000000000000
 
849
        QUAD $0x00000000ffffffff
 
850
        QUAD $0x0000000000000000
 
851
        QUAD $0x000000ffffffffff
 
852
        QUAD $0x0000000000000000
 
853
        QUAD $0x0000ffffffffffff
 
854
        QUAD $0x0000000000000000
 
855
        QUAD $0x00ffffffffffffff
 
856
        QUAD $0x0000000000000000
 
857
        QUAD $0xffffffffffffffff
 
858
        QUAD $0x0000000000000000
 
859
        QUAD $0xffffffffffffffff
 
860
        QUAD $0x00000000000000ff
 
861
        QUAD $0xffffffffffffffff
 
862
        QUAD $0x000000000000ffff
 
863
        QUAD $0xffffffffffffffff
 
864
        QUAD $0x0000000000ffffff
 
865
        QUAD $0xffffffffffffffff
 
866
        QUAD $0x00000000ffffffff
 
867
        QUAD $0xffffffffffffffff
 
868
        QUAD $0x000000ffffffffff
 
869
        QUAD $0xffffffffffffffff
 
870
        QUAD $0x0000ffffffffffff
 
871
        QUAD $0xffffffffffffffff
 
872
        QUAD $0x00ffffffffffffff
 
873
 
 
874
        // these are arguments to pshufb.  They move data down from
 
875
        // the high bytes of the register to the low bytes of the register.
 
876
        // index is how many bytes to move.
 
877
TEXT shifts(SB),7,$0
 
878
        QUAD $0x0000000000000000
 
879
        QUAD $0x0000000000000000
 
880
        QUAD $0xffffffffffffff0f
 
881
        QUAD $0xffffffffffffffff
 
882
        QUAD $0xffffffffffff0f0e
 
883
        QUAD $0xffffffffffffffff
 
884
        QUAD $0xffffffffff0f0e0d
 
885
        QUAD $0xffffffffffffffff
 
886
        QUAD $0xffffffff0f0e0d0c
 
887
        QUAD $0xffffffffffffffff
 
888
        QUAD $0xffffff0f0e0d0c0b
 
889
        QUAD $0xffffffffffffffff
 
890
        QUAD $0xffff0f0e0d0c0b0a
 
891
        QUAD $0xffffffffffffffff
 
892
        QUAD $0xff0f0e0d0c0b0a09
 
893
        QUAD $0xffffffffffffffff
 
894
        QUAD $0x0f0e0d0c0b0a0908
 
895
        QUAD $0xffffffffffffffff
 
896
        QUAD $0x0e0d0c0b0a090807
 
897
        QUAD $0xffffffffffffff0f
 
898
        QUAD $0x0d0c0b0a09080706
 
899
        QUAD $0xffffffffffff0f0e
 
900
        QUAD $0x0c0b0a0908070605
 
901
        QUAD $0xffffffffff0f0e0d
 
902
        QUAD $0x0b0a090807060504
 
903
        QUAD $0xffffffff0f0e0d0c
 
904
        QUAD $0x0a09080706050403
 
905
        QUAD $0xffffff0f0e0d0c0b
 
906
        QUAD $0x0908070605040302
 
907
        QUAD $0xffff0f0e0d0c0b0a
 
908
        QUAD $0x0807060504030201
 
909
        QUAD $0xff0f0e0d0c0b0a09
 
910
 
 
911
TEXT runtime·memeq(SB),7,$0
 
912
        MOVQ    a+0(FP), SI
 
913
        MOVQ    b+8(FP), DI
 
914
        MOVQ    count+16(FP), BX
 
915
        JMP     runtime·memeqbody(SB)
 
916
 
 
917
 
 
918
TEXT bytes·Equal(SB),7,$0
 
919
        MOVQ    a_len+8(FP), BX
 
920
        MOVQ    b_len+32(FP), CX
 
921
        XORQ    AX, AX
 
922
        CMPQ    BX, CX
 
923
        JNE     eqret
 
924
        MOVQ    a+0(FP), SI
 
925
        MOVQ    b+24(FP), DI
 
926
        CALL    runtime·memeqbody(SB)
 
927
eqret:
 
928
        MOVB    AX, ret+48(FP)
 
929
        RET
 
930
 
 
931
// a in SI
 
932
// b in DI
 
933
// count in BX
 
934
TEXT runtime·memeqbody(SB),7,$0
 
935
        XORQ    AX, AX
 
936
 
 
937
        CMPQ    BX, $8
 
938
        JB      small
 
939
        
 
940
        // 64 bytes at a time using xmm registers
 
941
hugeloop:
 
942
        CMPQ    BX, $64
 
943
        JB      bigloop
 
944
        MOVOU   (SI), X0
 
945
        MOVOU   (DI), X1
 
946
        MOVOU   16(SI), X2
 
947
        MOVOU   16(DI), X3
 
948
        MOVOU   32(SI), X4
 
949
        MOVOU   32(DI), X5
 
950
        MOVOU   48(SI), X6
 
951
        MOVOU   48(DI), X7
 
952
        PCMPEQB X1, X0
 
953
        PCMPEQB X3, X2
 
954
        PCMPEQB X5, X4
 
955
        PCMPEQB X7, X6
 
956
        PAND    X2, X0
 
957
        PAND    X6, X4
 
958
        PAND    X4, X0
 
959
        PMOVMSKB X0, DX
 
960
        ADDQ    $64, SI
 
961
        ADDQ    $64, DI
 
962
        SUBQ    $64, BX
 
963
        CMPL    DX, $0xffff
 
964
        JEQ     hugeloop
 
965
        RET
 
966
 
 
967
        // 8 bytes at a time using 64-bit register
 
968
bigloop:
 
969
        CMPQ    BX, $8
 
970
        JBE     leftover
 
971
        MOVQ    (SI), CX
 
972
        MOVQ    (DI), DX
 
973
        ADDQ    $8, SI
 
974
        ADDQ    $8, DI
 
975
        SUBQ    $8, BX
 
976
        CMPQ    CX, DX
 
977
        JEQ     bigloop
 
978
        RET
 
979
 
 
980
        // remaining 0-8 bytes
 
981
leftover:
 
982
        MOVQ    -8(SI)(BX*1), CX
 
983
        MOVQ    -8(DI)(BX*1), DX
 
984
        CMPQ    CX, DX
 
985
        SETEQ   AX
 
986
        RET
 
987
 
 
988
small:
 
989
        CMPQ    BX, $0
 
990
        JEQ     equal
 
991
 
 
992
        LEAQ    0(BX*8), CX
 
993
        NEGQ    CX
 
994
 
 
995
        CMPB    SI, $0xf8
 
996
        JA      si_high
 
997
 
 
998
        // load at SI won't cross a page boundary.
 
999
        MOVQ    (SI), SI
 
1000
        JMP     si_finish
 
1001
si_high:
 
1002
        // address ends in 11111xxx.  Load up to bytes we want, move to correct position.
 
1003
        MOVQ    -8(SI)(BX*1), SI
 
1004
        SHRQ    CX, SI
 
1005
si_finish:
 
1006
 
 
1007
        // same for DI.
 
1008
        CMPB    DI, $0xf8
 
1009
        JA      di_high
 
1010
        MOVQ    (DI), DI
 
1011
        JMP     di_finish
 
1012
di_high:
 
1013
        MOVQ    -8(DI)(BX*1), DI
 
1014
        SHRQ    CX, DI
 
1015
di_finish:
 
1016
 
 
1017
        SUBQ    SI, DI
 
1018
        SHLQ    CX, DI
 
1019
equal:
 
1020
        SETEQ   AX
 
1021
        RET