]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_amd64.s
[dev.cc] all: merge master (48469a2) into dev.cc
[gostls13.git] / src / runtime / asm_amd64.s
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "go_asm.h"
6 #include "go_tls.h"
7 #include "funcdata.h"
8 #include "textflag.h"
9
10 TEXT runtime·rt0_go(SB),NOSPLIT,$0
11         // copy arguments forward on an even stack
12         MOVQ    DI, AX          // argc
13         MOVQ    SI, BX          // argv
14         SUBQ    $(4*8+7), SP            // 2args 2auto
15         ANDQ    $~15, SP
16         MOVQ    AX, 16(SP)
17         MOVQ    BX, 24(SP)
18         
19         // create istack out of the given (operating system) stack.
20         // _cgo_init may update stackguard.
21         MOVQ    $runtime·g0(SB), DI
22         LEAQ    (-64*1024+104)(SP), BX
23         MOVQ    BX, g_stackguard0(DI)
24         MOVQ    BX, g_stackguard1(DI)
25         MOVQ    BX, (g_stack+stack_lo)(DI)
26         MOVQ    SP, (g_stack+stack_hi)(DI)
27
28         // find out information about the processor we're on
29         MOVQ    $0, AX
30         CPUID
31         CMPQ    AX, $0
32         JE      nocpuinfo
33
34         // Figure out how to serialize RDTSC.
35         // On Intel processors LFENCE is enough. AMD requires MFENCE.
36         // Don't know about the rest, so let's do MFENCE.
37         CMPL    BX, $0x756E6547  // "Genu"
38         JNE     notintel
39         CMPL    DX, $0x49656E69  // "ineI"
40         JNE     notintel
41         CMPL    CX, $0x6C65746E  // "ntel"
42         JNE     notintel
43         MOVB    $1, runtime·lfenceBeforeRdtsc(SB)
44 notintel:
45
46         MOVQ    $1, AX
47         CPUID
48         MOVL    CX, runtime·cpuid_ecx(SB)
49         MOVL    DX, runtime·cpuid_edx(SB)
50 nocpuinfo:      
51         
52         // if there is an _cgo_init, call it.
53         MOVQ    _cgo_init(SB), AX
54         TESTQ   AX, AX
55         JZ      needtls
56         // g0 already in DI
57         MOVQ    DI, CX  // Win64 uses CX for first parameter
58         MOVQ    $setg_gcc<>(SB), SI
59         CALL    AX
60
61         // update stackguard after _cgo_init
62         MOVQ    $runtime·g0(SB), CX
63         MOVQ    (g_stack+stack_lo)(CX), AX
64         ADDQ    $const__StackGuard, AX
65         MOVQ    AX, g_stackguard0(CX)
66         MOVQ    AX, g_stackguard1(CX)
67
68         CMPL    runtime·iswindows(SB), $0
69         JEQ ok
70 needtls:
71         // skip TLS setup on Plan 9
72         CMPL    runtime·isplan9(SB), $1
73         JEQ ok
74         // skip TLS setup on Solaris
75         CMPL    runtime·issolaris(SB), $1
76         JEQ ok
77
78         LEAQ    runtime·tls0(SB), DI
79         CALL    runtime·settls(SB)
80
81         // store through it, to make sure it works
82         get_tls(BX)
83         MOVQ    $0x123, g(BX)
84         MOVQ    runtime·tls0(SB), AX
85         CMPQ    AX, $0x123
86         JEQ 2(PC)
87         MOVL    AX, 0   // abort
88 ok:
89         // set the per-goroutine and per-mach "registers"
90         get_tls(BX)
91         LEAQ    runtime·g0(SB), CX
92         MOVQ    CX, g(BX)
93         LEAQ    runtime·m0(SB), AX
94
95         // save m->g0 = g0
96         MOVQ    CX, m_g0(AX)
97         // save m0 to g0->m
98         MOVQ    AX, g_m(CX)
99
100         CLD                             // convention is D is always left cleared
101         CALL    runtime·check(SB)
102
103         MOVL    16(SP), AX              // copy argc
104         MOVL    AX, 0(SP)
105         MOVQ    24(SP), AX              // copy argv
106         MOVQ    AX, 8(SP)
107         CALL    runtime·args(SB)
108         CALL    runtime·osinit(SB)
109         CALL    runtime·schedinit(SB)
110
111         // create a new goroutine to start program
112         MOVQ    $runtime·main·f(SB), AX               // entry
113         PUSHQ   AX
114         PUSHQ   $0                      // arg size
115         CALL    runtime·newproc(SB)
116         POPQ    AX
117         POPQ    AX
118
119         // start this M
120         CALL    runtime·mstart(SB)
121
122         MOVL    $0xf1, 0xf1  // crash
123         RET
124
125 DATA    runtime·main·f+0(SB)/8,$runtime·main(SB)
126 GLOBL   runtime·main·f(SB),RODATA,$8
127
128 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
129         BYTE    $0xcc
130         RET
131
132 TEXT runtime·asminit(SB),NOSPLIT,$0-0
133         // No per-thread init.
134         RET
135
136 /*
137  *  go-routine
138  */
139
140 // void gosave(Gobuf*)
141 // save state in Gobuf; setjmp
142 TEXT runtime·gosave(SB), NOSPLIT, $0-8
143         MOVQ    buf+0(FP), AX           // gobuf
144         LEAQ    buf+0(FP), BX           // caller's SP
145         MOVQ    BX, gobuf_sp(AX)
146         MOVQ    0(SP), BX               // caller's PC
147         MOVQ    BX, gobuf_pc(AX)
148         MOVQ    $0, gobuf_ret(AX)
149         MOVQ    $0, gobuf_ctxt(AX)
150         MOVQ    BP, gobuf_bp(AX)
151         get_tls(CX)
152         MOVQ    g(CX), BX
153         MOVQ    BX, gobuf_g(AX)
154         RET
155
156 // void gogo(Gobuf*)
157 // restore state from Gobuf; longjmp
158 TEXT runtime·gogo(SB), NOSPLIT, $0-8
159         MOVQ    buf+0(FP), BX           // gobuf
160         MOVQ    gobuf_g(BX), DX
161         MOVQ    0(DX), CX               // make sure g != nil
162         get_tls(CX)
163         MOVQ    DX, g(CX)
164         MOVQ    gobuf_sp(BX), SP        // restore SP
165         MOVQ    gobuf_ret(BX), AX
166         MOVQ    gobuf_ctxt(BX), DX
167         MOVQ    gobuf_bp(BX), BP
168         MOVQ    $0, gobuf_sp(BX)        // clear to help garbage collector
169         MOVQ    $0, gobuf_ret(BX)
170         MOVQ    $0, gobuf_ctxt(BX)
171         MOVQ    $0, gobuf_bp(BX)
172         MOVQ    gobuf_pc(BX), BX
173         JMP     BX
174
175 // func mcall(fn func(*g))
176 // Switch to m->g0's stack, call fn(g).
177 // Fn must never return.  It should gogo(&g->sched)
178 // to keep running g.
179 TEXT runtime·mcall(SB), NOSPLIT, $0-8
180         MOVQ    fn+0(FP), DI
181         
182         get_tls(CX)
183         MOVQ    g(CX), AX       // save state in g->sched
184         MOVQ    0(SP), BX       // caller's PC
185         MOVQ    BX, (g_sched+gobuf_pc)(AX)
186         LEAQ    fn+0(FP), BX    // caller's SP
187         MOVQ    BX, (g_sched+gobuf_sp)(AX)
188         MOVQ    AX, (g_sched+gobuf_g)(AX)
189         MOVQ    BP, (g_sched+gobuf_bp)(AX)
190
191         // switch to m->g0 & its stack, call fn
192         MOVQ    g(CX), BX
193         MOVQ    g_m(BX), BX
194         MOVQ    m_g0(BX), SI
195         CMPQ    SI, AX  // if g == m->g0 call badmcall
196         JNE     3(PC)
197         MOVQ    $runtime·badmcall(SB), AX
198         JMP     AX
199         MOVQ    SI, g(CX)       // g = m->g0
200         MOVQ    (g_sched+gobuf_sp)(SI), SP      // sp = m->g0->sched.sp
201         PUSHQ   AX
202         MOVQ    DI, DX
203         MOVQ    0(DI), DI
204         CALL    DI
205         POPQ    AX
206         MOVQ    $runtime·badmcall2(SB), AX
207         JMP     AX
208         RET
209
210 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
211 // of the G stack.  We need to distinguish the routine that
212 // lives at the bottom of the G stack from the one that lives
213 // at the top of the system stack because the one at the top of
214 // the system stack terminates the stack walk (see topofstack()).
215 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
216         RET
217
218 // func systemstack(fn func())
219 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
220         MOVQ    fn+0(FP), DI    // DI = fn
221         get_tls(CX)
222         MOVQ    g(CX), AX       // AX = g
223         MOVQ    g_m(AX), BX     // BX = m
224
225         MOVQ    m_gsignal(BX), DX       // DX = gsignal
226         CMPQ    AX, DX
227         JEQ     noswitch
228
229         MOVQ    m_g0(BX), DX    // DX = g0
230         CMPQ    AX, DX
231         JEQ     noswitch
232
233         MOVQ    m_curg(BX), R8
234         CMPQ    AX, R8
235         JEQ     switch
236         
237         // Bad: g is not gsignal, not g0, not curg. What is it?
238         MOVQ    $runtime·badsystemstack(SB), AX
239         CALL    AX
240
241 switch:
242         // save our state in g->sched.  Pretend to
243         // be systemstack_switch if the G stack is scanned.
244         MOVQ    $runtime·systemstack_switch(SB), SI
245         MOVQ    SI, (g_sched+gobuf_pc)(AX)
246         MOVQ    SP, (g_sched+gobuf_sp)(AX)
247         MOVQ    AX, (g_sched+gobuf_g)(AX)
248         MOVQ    BP, (g_sched+gobuf_bp)(AX)
249
250         // switch to g0
251         MOVQ    DX, g(CX)
252         MOVQ    (g_sched+gobuf_sp)(DX), BX
253         // make it look like mstart called systemstack on g0, to stop traceback
254         SUBQ    $8, BX
255         MOVQ    $runtime·mstart(SB), DX
256         MOVQ    DX, 0(BX)
257         MOVQ    BX, SP
258
259         // call target function
260         MOVQ    DI, DX
261         MOVQ    0(DI), DI
262         CALL    DI
263
264         // switch back to g
265         get_tls(CX)
266         MOVQ    g(CX), AX
267         MOVQ    g_m(AX), BX
268         MOVQ    m_curg(BX), AX
269         MOVQ    AX, g(CX)
270         MOVQ    (g_sched+gobuf_sp)(AX), SP
271         MOVQ    $0, (g_sched+gobuf_sp)(AX)
272         RET
273
274 noswitch:
275         // already on m stack, just call directly
276         MOVQ    DI, DX
277         MOVQ    0(DI), DI
278         CALL    DI
279         RET
280
281 /*
282  * support for morestack
283  */
284
285 // Called during function prolog when more stack is needed.
286 //
287 // The traceback routines see morestack on a g0 as being
288 // the top of a stack (for example, morestack calling newstack
289 // calling the scheduler calling newm calling gc), so we must
290 // record an argument size. For that purpose, it has no arguments.
291 TEXT runtime·morestack(SB),NOSPLIT,$0-0
292         // Cannot grow scheduler stack (m->g0).
293         get_tls(CX)
294         MOVQ    g(CX), BX
295         MOVQ    g_m(BX), BX
296         MOVQ    m_g0(BX), SI
297         CMPQ    g(CX), SI
298         JNE     2(PC)
299         INT     $3
300
301         // Cannot grow signal stack (m->gsignal).
302         MOVQ    m_gsignal(BX), SI
303         CMPQ    g(CX), SI
304         JNE     2(PC)
305         INT     $3
306
307         // Called from f.
308         // Set m->morebuf to f's caller.
309         MOVQ    8(SP), AX       // f's caller's PC
310         MOVQ    AX, (m_morebuf+gobuf_pc)(BX)
311         LEAQ    16(SP), AX      // f's caller's SP
312         MOVQ    AX, (m_morebuf+gobuf_sp)(BX)
313         get_tls(CX)
314         MOVQ    g(CX), SI
315         MOVQ    SI, (m_morebuf+gobuf_g)(BX)
316
317         // Set g->sched to context in f.
318         MOVQ    0(SP), AX // f's PC
319         MOVQ    AX, (g_sched+gobuf_pc)(SI)
320         MOVQ    SI, (g_sched+gobuf_g)(SI)
321         LEAQ    8(SP), AX // f's SP
322         MOVQ    AX, (g_sched+gobuf_sp)(SI)
323         MOVQ    DX, (g_sched+gobuf_ctxt)(SI)
324         MOVQ    BP, (g_sched+gobuf_bp)(SI)
325
326         // Call newstack on m->g0's stack.
327         MOVQ    m_g0(BX), BX
328         MOVQ    BX, g(CX)
329         MOVQ    (g_sched+gobuf_sp)(BX), SP
330         CALL    runtime·newstack(SB)
331         MOVQ    $0, 0x1003      // crash if newstack returns
332         RET
333
334 // morestack but not preserving ctxt.
335 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
336         MOVL    $0, DX
337         JMP     runtime·morestack(SB)
338
339 // reflectcall: call a function with the given argument list
340 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
341 // we don't have variable-sized frames, so we use a small number
342 // of constant-sized-frame functions to encode a few bits of size in the pc.
343 // Caution: ugly multiline assembly macros in your future!
344
345 #define DISPATCH(NAME,MAXSIZE)          \
346         CMPQ    CX, $MAXSIZE;           \
347         JA      3(PC);                  \
348         MOVQ    $NAME(SB), AX;          \
349         JMP     AX
350 // Note: can't just "JMP NAME(SB)" - bad inlining results.
351
352 TEXT reflect·call(SB), NOSPLIT, $0-0
353         JMP     ·reflectcall(SB)
354
355 TEXT ·reflectcall(SB), NOSPLIT, $0-32
356         MOVLQZX argsize+24(FP), CX
357         // NOTE(rsc): No call16, because CALLFN needs four words
358         // of argument space to invoke callwritebarrier.
359         DISPATCH(runtime·call32, 32)
360         DISPATCH(runtime·call64, 64)
361         DISPATCH(runtime·call128, 128)
362         DISPATCH(runtime·call256, 256)
363         DISPATCH(runtime·call512, 512)
364         DISPATCH(runtime·call1024, 1024)
365         DISPATCH(runtime·call2048, 2048)
366         DISPATCH(runtime·call4096, 4096)
367         DISPATCH(runtime·call8192, 8192)
368         DISPATCH(runtime·call16384, 16384)
369         DISPATCH(runtime·call32768, 32768)
370         DISPATCH(runtime·call65536, 65536)
371         DISPATCH(runtime·call131072, 131072)
372         DISPATCH(runtime·call262144, 262144)
373         DISPATCH(runtime·call524288, 524288)
374         DISPATCH(runtime·call1048576, 1048576)
375         DISPATCH(runtime·call2097152, 2097152)
376         DISPATCH(runtime·call4194304, 4194304)
377         DISPATCH(runtime·call8388608, 8388608)
378         DISPATCH(runtime·call16777216, 16777216)
379         DISPATCH(runtime·call33554432, 33554432)
380         DISPATCH(runtime·call67108864, 67108864)
381         DISPATCH(runtime·call134217728, 134217728)
382         DISPATCH(runtime·call268435456, 268435456)
383         DISPATCH(runtime·call536870912, 536870912)
384         DISPATCH(runtime·call1073741824, 1073741824)
385         MOVQ    $runtime·badreflectcall(SB), AX
386         JMP     AX
387
388 #define CALLFN(NAME,MAXSIZE)                    \
389 TEXT NAME(SB), WRAPPER, $MAXSIZE-32;            \
390         NO_LOCAL_POINTERS;                      \
391         /* copy arguments to stack */           \
392         MOVQ    argptr+16(FP), SI;              \
393         MOVLQZX argsize+24(FP), CX;             \
394         MOVQ    SP, DI;                         \
395         REP;MOVSB;                              \
396         /* call function */                     \
397         MOVQ    f+8(FP), DX;                    \
398         PCDATA  $PCDATA_StackMapIndex, $0;      \
399         CALL    (DX);                           \
400         /* copy return values back */           \
401         MOVQ    argptr+16(FP), DI;              \
402         MOVLQZX argsize+24(FP), CX;             \
403         MOVLQZX retoffset+28(FP), BX;           \
404         MOVQ    SP, SI;                         \
405         ADDQ    BX, DI;                         \
406         ADDQ    BX, SI;                         \
407         SUBQ    BX, CX;                         \
408         REP;MOVSB;                              \
409         /* execute write barrier updates */     \
410         MOVQ    argtype+0(FP), DX;              \
411         MOVQ    argptr+16(FP), DI;              \
412         MOVLQZX argsize+24(FP), CX;             \
413         MOVLQZX retoffset+28(FP), BX;           \
414         MOVQ    DX, 0(SP);                      \
415         MOVQ    DI, 8(SP);                      \
416         MOVQ    CX, 16(SP);                     \
417         MOVQ    BX, 24(SP);                     \
418         CALL    runtime·callwritebarrier(SB);  \
419         RET
420
421 CALLFN(·call32, 32)
422 CALLFN(·call64, 64)
423 CALLFN(·call128, 128)
424 CALLFN(·call256, 256)
425 CALLFN(·call512, 512)
426 CALLFN(·call1024, 1024)
427 CALLFN(·call2048, 2048)
428 CALLFN(·call4096, 4096)
429 CALLFN(·call8192, 8192)
430 CALLFN(·call16384, 16384)
431 CALLFN(·call32768, 32768)
432 CALLFN(·call65536, 65536)
433 CALLFN(·call131072, 131072)
434 CALLFN(·call262144, 262144)
435 CALLFN(·call524288, 524288)
436 CALLFN(·call1048576, 1048576)
437 CALLFN(·call2097152, 2097152)
438 CALLFN(·call4194304, 4194304)
439 CALLFN(·call8388608, 8388608)
440 CALLFN(·call16777216, 16777216)
441 CALLFN(·call33554432, 33554432)
442 CALLFN(·call67108864, 67108864)
443 CALLFN(·call134217728, 134217728)
444 CALLFN(·call268435456, 268435456)
445 CALLFN(·call536870912, 536870912)
446 CALLFN(·call1073741824, 1073741824)
447
448 // bool cas(int32 *val, int32 old, int32 new)
449 // Atomically:
450 //      if(*val == old){
451 //              *val = new;
452 //              return 1;
453 //      } else
454 //              return 0;
455 TEXT runtime·cas(SB), NOSPLIT, $0-17
456         MOVQ    ptr+0(FP), BX
457         MOVL    old+8(FP), AX
458         MOVL    new+12(FP), CX
459         LOCK
460         CMPXCHGL        CX, 0(BX)
461         SETEQ   ret+16(FP)
462         RET
463
464 // bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
465 // Atomically:
466 //      if(*val == *old){
467 //              *val = new;
468 //              return 1;
469 //      } else {
470 //              return 0;
471 //      }
472 TEXT runtime·cas64(SB), NOSPLIT, $0-25
473         MOVQ    ptr+0(FP), BX
474         MOVQ    old+8(FP), AX
475         MOVQ    new+16(FP), CX
476         LOCK
477         CMPXCHGQ        CX, 0(BX)
478         SETEQ   ret+24(FP)
479         RET
480         
481 TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
482         JMP     runtime·cas64(SB)
483
484 TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-16
485         JMP     runtime·atomicload64(SB)
486
487 TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-16
488         JMP     runtime·atomicload64(SB)
489
490 TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
491         JMP     runtime·atomicstore64(SB)
492
493 // bool casp(void **val, void *old, void *new)
494 // Atomically:
495 //      if(*val == old){
496 //              *val = new;
497 //              return 1;
498 //      } else
499 //              return 0;
500 TEXT runtime·casp1(SB), NOSPLIT, $0-25
501         MOVQ    ptr+0(FP), BX
502         MOVQ    old+8(FP), AX
503         MOVQ    new+16(FP), CX
504         LOCK
505         CMPXCHGQ        CX, 0(BX)
506         SETEQ   ret+24(FP)
507         RET
508
509 // uint32 xadd(uint32 volatile *val, int32 delta)
510 // Atomically:
511 //      *val += delta;
512 //      return *val;
513 TEXT runtime·xadd(SB), NOSPLIT, $0-20
514         MOVQ    ptr+0(FP), BX
515         MOVL    delta+8(FP), AX
516         MOVL    AX, CX
517         LOCK
518         XADDL   AX, 0(BX)
519         ADDL    CX, AX
520         MOVL    AX, ret+16(FP)
521         RET
522
523 TEXT runtime·xadd64(SB), NOSPLIT, $0-24
524         MOVQ    ptr+0(FP), BX
525         MOVQ    delta+8(FP), AX
526         MOVQ    AX, CX
527         LOCK
528         XADDQ   AX, 0(BX)
529         ADDQ    CX, AX
530         MOVQ    AX, ret+16(FP)
531         RET
532
533 TEXT runtime·xchg(SB), NOSPLIT, $0-20
534         MOVQ    ptr+0(FP), BX
535         MOVL    new+8(FP), AX
536         XCHGL   AX, 0(BX)
537         MOVL    AX, ret+16(FP)
538         RET
539
540 TEXT runtime·xchg64(SB), NOSPLIT, $0-24
541         MOVQ    ptr+0(FP), BX
542         MOVQ    new+8(FP), AX
543         XCHGQ   AX, 0(BX)
544         MOVQ    AX, ret+16(FP)
545         RET
546
547 TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
548         MOVQ    ptr+0(FP), BX
549         MOVQ    new+8(FP), AX
550         XCHGQ   AX, 0(BX)
551         MOVQ    AX, ret+16(FP)
552         RET
553
554 TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
555         JMP     runtime·xchg64(SB)
556
557 TEXT runtime·procyield(SB),NOSPLIT,$0-0
558         MOVL    cycles+0(FP), AX
559 again:
560         PAUSE
561         SUBL    $1, AX
562         JNZ     again
563         RET
564
565 TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
566         MOVQ    ptr+0(FP), BX
567         MOVQ    val+8(FP), AX
568         XCHGQ   AX, 0(BX)
569         RET
570
571 TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
572         MOVQ    ptr+0(FP), BX
573         MOVL    val+8(FP), AX
574         XCHGL   AX, 0(BX)
575         RET
576
577 TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
578         MOVQ    ptr+0(FP), BX
579         MOVQ    val+8(FP), AX
580         XCHGQ   AX, 0(BX)
581         RET
582
583 // void runtime·atomicor8(byte volatile*, byte);
584 TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
585         MOVQ    ptr+0(FP), AX
586         MOVB    val+8(FP), BX
587         LOCK
588         ORB     BX, (AX)
589         RET
590
591 // void jmpdefer(fn, sp);
592 // called from deferreturn.
593 // 1. pop the caller
594 // 2. sub 5 bytes from the callers return
595 // 3. jmp to the argument
596 TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
597         MOVQ    fv+0(FP), DX    // fn
598         MOVQ    argp+8(FP), BX  // caller sp
599         LEAQ    -8(BX), SP      // caller sp after CALL
600         SUBQ    $5, (SP)        // return to CALL again
601         MOVQ    0(DX), BX
602         JMP     BX      // but first run the deferred function
603
604 // Save state of caller into g->sched. Smashes R8, R9.
605 TEXT gosave<>(SB),NOSPLIT,$0
606         get_tls(R8)
607         MOVQ    g(R8), R8
608         MOVQ    0(SP), R9
609         MOVQ    R9, (g_sched+gobuf_pc)(R8)
610         LEAQ    8(SP), R9
611         MOVQ    R9, (g_sched+gobuf_sp)(R8)
612         MOVQ    $0, (g_sched+gobuf_ret)(R8)
613         MOVQ    $0, (g_sched+gobuf_ctxt)(R8)
614         MOVQ    BP, (g_sched+gobuf_bp)(R8)
615         RET
616
617 // asmcgocall(void(*fn)(void*), void *arg)
618 // Call fn(arg) on the scheduler stack,
619 // aligned appropriately for the gcc ABI.
620 // See cgocall.c for more details.
621 TEXT ·asmcgocall(SB),NOSPLIT,$0-16
622         MOVQ    fn+0(FP), AX
623         MOVQ    arg+8(FP), BX
624         CALL    asmcgocall<>(SB)
625         RET
626
627 TEXT ·asmcgocall_errno(SB),NOSPLIT,$0-20
628         MOVQ    fn+0(FP), AX
629         MOVQ    arg+8(FP), BX
630         CALL    asmcgocall<>(SB)
631         MOVL    AX, ret+16(FP)
632         RET
633
634 // asmcgocall common code. fn in AX, arg in BX. returns errno in AX.
635 TEXT asmcgocall<>(SB),NOSPLIT,$0-0
636         MOVQ    SP, DX
637
638         // Figure out if we need to switch to m->g0 stack.
639         // We get called to create new OS threads too, and those
640         // come in on the m->g0 stack already.
641         get_tls(CX)
642         MOVQ    g(CX), R8
643         MOVQ    g_m(R8), R8
644         MOVQ    m_g0(R8), SI
645         MOVQ    g(CX), DI
646         CMPQ    SI, DI
647         JEQ     nosave
648         MOVQ    m_gsignal(R8), SI
649         CMPQ    SI, DI
650         JEQ     nosave
651         
652         MOVQ    m_g0(R8), SI
653         CALL    gosave<>(SB)
654         MOVQ    SI, g(CX)
655         MOVQ    (g_sched+gobuf_sp)(SI), SP
656 nosave:
657
658         // Now on a scheduling stack (a pthread-created stack).
659         // Make sure we have enough room for 4 stack-backed fast-call
660         // registers as per windows amd64 calling convention.
661         SUBQ    $64, SP
662         ANDQ    $~15, SP        // alignment for gcc ABI
663         MOVQ    DI, 48(SP)      // save g
664         MOVQ    (g_stack+stack_hi)(DI), DI
665         SUBQ    DX, DI
666         MOVQ    DI, 40(SP)      // save depth in stack (can't just save SP, as stack might be copied during a callback)
667         MOVQ    BX, DI          // DI = first argument in AMD64 ABI
668         MOVQ    BX, CX          // CX = first argument in Win64
669         CALL    AX
670
671         // Restore registers, g, stack pointer.
672         get_tls(CX)
673         MOVQ    48(SP), DI
674         MOVQ    (g_stack+stack_hi)(DI), SI
675         SUBQ    40(SP), SI
676         MOVQ    DI, g(CX)
677         MOVQ    SI, SP
678         RET
679
680 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
681 // Turn the fn into a Go func (by taking its address) and call
682 // cgocallback_gofunc.
683 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
684         LEAQ    fn+0(FP), AX
685         MOVQ    AX, 0(SP)
686         MOVQ    frame+8(FP), AX
687         MOVQ    AX, 8(SP)
688         MOVQ    framesize+16(FP), AX
689         MOVQ    AX, 16(SP)
690         MOVQ    $runtime·cgocallback_gofunc(SB), AX
691         CALL    AX
692         RET
693
694 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
695 // See cgocall.c for more details.
696 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
697         NO_LOCAL_POINTERS
698
699         // If g is nil, Go did not create the current thread.
700         // Call needm to obtain one m for temporary use.
701         // In this case, we're running on the thread stack, so there's
702         // lots of space, but the linker doesn't know. Hide the call from
703         // the linker analysis by using an indirect call through AX.
704         get_tls(CX)
705 #ifdef GOOS_windows
706         MOVL    $0, BX
707         CMPQ    CX, $0
708         JEQ     2(PC)
709 #endif
710         MOVQ    g(CX), BX
711         CMPQ    BX, $0
712         JEQ     needm
713         MOVQ    g_m(BX), BX
714         MOVQ    BX, R8 // holds oldm until end of function
715         JMP     havem
716 needm:
717         MOVQ    $0, 0(SP)
718         MOVQ    $runtime·needm(SB), AX
719         CALL    AX
720         MOVQ    0(SP), R8
721         get_tls(CX)
722         MOVQ    g(CX), BX
723         MOVQ    g_m(BX), BX
724         
725         // Set m->sched.sp = SP, so that if a panic happens
726         // during the function we are about to execute, it will
727         // have a valid SP to run on the g0 stack.
728         // The next few lines (after the havem label)
729         // will save this SP onto the stack and then write
730         // the same SP back to m->sched.sp. That seems redundant,
731         // but if an unrecovered panic happens, unwindm will
732         // restore the g->sched.sp from the stack location
733         // and then systemstack will try to use it. If we don't set it here,
734         // that restored SP will be uninitialized (typically 0) and
735         // will not be usable.
736         MOVQ    m_g0(BX), SI
737         MOVQ    SP, (g_sched+gobuf_sp)(SI)
738
739 havem:
740         // Now there's a valid m, and we're running on its m->g0.
741         // Save current m->g0->sched.sp on stack and then set it to SP.
742         // Save current sp in m->g0->sched.sp in preparation for
743         // switch back to m->curg stack.
744         // NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
745         MOVQ    m_g0(BX), SI
746         MOVQ    (g_sched+gobuf_sp)(SI), AX
747         MOVQ    AX, 0(SP)
748         MOVQ    SP, (g_sched+gobuf_sp)(SI)
749
750         // Switch to m->curg stack and call runtime.cgocallbackg.
751         // Because we are taking over the execution of m->curg
752         // but *not* resuming what had been running, we need to
753         // save that information (m->curg->sched) so we can restore it.
754         // We can restore m->curg->sched.sp easily, because calling
755         // runtime.cgocallbackg leaves SP unchanged upon return.
756         // To save m->curg->sched.pc, we push it onto the stack.
757         // This has the added benefit that it looks to the traceback
758         // routine like cgocallbackg is going to return to that
759         // PC (because the frame we allocate below has the same
760         // size as cgocallback_gofunc's frame declared above)
761         // so that the traceback will seamlessly trace back into
762         // the earlier calls.
763         //
764         // In the new goroutine, 0(SP) holds the saved R8.
765         MOVQ    m_curg(BX), SI
766         MOVQ    SI, g(CX)
767         MOVQ    (g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
768         MOVQ    (g_sched+gobuf_pc)(SI), BX
769         MOVQ    BX, -8(DI)
770         // Compute the size of the frame, including return PC and, if
771         // GOEXPERIMENT=framepointer, the saved based pointer
772         LEAQ    fv+0(FP), AX
773         SUBQ    SP, AX
774         SUBQ    AX, DI
775         MOVQ    DI, SP
776
777         MOVQ    R8, 0(SP)
778         CALL    runtime·cgocallbackg(SB)
779         MOVQ    0(SP), R8
780
781         // Compute the size of the frame again.  FP and SP have
782         // completely different values here than they did above,
783         // but only their difference matters.
784         LEAQ    fv+0(FP), AX
785         SUBQ    SP, AX
786
787         // Restore g->sched (== m->curg->sched) from saved values.
788         get_tls(CX)
789         MOVQ    g(CX), SI
790         MOVQ    SP, DI
791         ADDQ    AX, DI
792         MOVQ    -8(DI), BX
793         MOVQ    BX, (g_sched+gobuf_pc)(SI)
794         MOVQ    DI, (g_sched+gobuf_sp)(SI)
795
796         // Switch back to m->g0's stack and restore m->g0->sched.sp.
797         // (Unlike m->curg, the g0 goroutine never uses sched.pc,
798         // so we do not have to restore it.)
799         MOVQ    g(CX), BX
800         MOVQ    g_m(BX), BX
801         MOVQ    m_g0(BX), SI
802         MOVQ    SI, g(CX)
803         MOVQ    (g_sched+gobuf_sp)(SI), SP
804         MOVQ    0(SP), AX
805         MOVQ    AX, (g_sched+gobuf_sp)(SI)
806         
807         // If the m on entry was nil, we called needm above to borrow an m
808         // for the duration of the call. Since the call is over, return it with dropm.
809         CMPQ    R8, $0
810         JNE 3(PC)
811         MOVQ    $runtime·dropm(SB), AX
812         CALL    AX
813
814         // Done!
815         RET
816
817 // void setg(G*); set g. for use by needm.
818 TEXT runtime·setg(SB), NOSPLIT, $0-8
819         MOVQ    gg+0(FP), BX
820 #ifdef GOOS_windows
821         CMPQ    BX, $0
822         JNE     settls
823         MOVQ    $0, 0x28(GS)
824         RET
825 settls:
826         MOVQ    g_m(BX), AX
827         LEAQ    m_tls(AX), AX
828         MOVQ    AX, 0x28(GS)
829 #endif
830         get_tls(CX)
831         MOVQ    BX, g(CX)
832         RET
833
834 // void setg_gcc(G*); set g called from gcc.
835 TEXT setg_gcc<>(SB),NOSPLIT,$0
836         get_tls(AX)
837         MOVQ    DI, g(AX)
838         RET
839
840 // check that SP is in range [g->stack.lo, g->stack.hi)
841 TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
842         get_tls(CX)
843         MOVQ    g(CX), AX
844         CMPQ    (g_stack+stack_hi)(AX), SP
845         JHI     2(PC)
846         INT     $3
847         CMPQ    SP, (g_stack+stack_lo)(AX)
848         JHI     2(PC)
849         INT     $3
850         RET
851
852 TEXT runtime·getcallerpc(SB),NOSPLIT,$0-16
853         MOVQ    argp+0(FP),AX           // addr of first arg
854         MOVQ    -8(AX),AX               // get calling pc
855         MOVQ    AX, ret+8(FP)
856         RET
857
858 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$0-16
859         MOVQ    p+0(FP),AX              // addr of first arg
860         MOVQ    -8(AX),AX               // get calling pc
861         MOVQ    AX,ret+8(FP)
862         RET
863
864 TEXT runtime·setcallerpc(SB),NOSPLIT,$0-16
865         MOVQ    argp+0(FP),AX           // addr of first arg
866         MOVQ    pc+8(FP), BX
867         MOVQ    BX, -8(AX)              // set calling pc
868         RET
869
870 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
871         MOVQ    argp+0(FP), AX
872         MOVQ    AX, ret+8(FP)
873         RET
874
875 // func gogetcallersp(p unsafe.Pointer) uintptr
876 TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
877         MOVQ    p+0(FP),AX              // addr of first arg
878         MOVQ    AX, ret+8(FP)
879         RET
880
881 // func cputicks() int64
882 TEXT runtime·cputicks(SB),NOSPLIT,$0-0
883         CMPB    runtime·lfenceBeforeRdtsc(SB), $1
884         JNE     mfence
885         BYTE    $0x0f; BYTE $0xae; BYTE $0xe8 // LFENCE
886         JMP     done
887 mfence:
888         BYTE    $0x0f; BYTE $0xae; BYTE $0xf0 // MFENCE
889 done:
890         RDTSC
891         SHLQ    $32, DX
892         ADDQ    DX, AX
893         MOVQ    AX, ret+0(FP)
894         RET
895
896 // memhash_varlen(p unsafe.Pointer, h seed) uintptr
897 // redirects to memhash(p, h, size) using the size
898 // stored in the closure.
899 TEXT runtime·memhash_varlen(SB),NOSPLIT,$32-24
900         GO_ARGS
901         NO_LOCAL_POINTERS
902         MOVQ    p+0(FP), AX
903         MOVQ    h+8(FP), BX
904         MOVQ    8(DX), CX
905         MOVQ    AX, 0(SP)
906         MOVQ    BX, 8(SP)
907         MOVQ    CX, 16(SP)
908         CALL    runtime·memhash(SB)
909         MOVQ    24(SP), AX
910         MOVQ    AX, ret+16(FP)
911         RET
912
913 // hash function using AES hardware instructions
914 TEXT runtime·aeshash(SB),NOSPLIT,$0-32
915         MOVQ    p+0(FP), AX     // ptr to data
916         MOVQ    s+16(FP), CX    // size
917         LEAQ    ret+24(FP), DX
918         JMP     runtime·aeshashbody(SB)
919
920 TEXT runtime·aeshashstr(SB),NOSPLIT,$0-24
921         MOVQ    p+0(FP), AX     // ptr to string struct
922         MOVQ    8(AX), CX       // length of string
923         MOVQ    (AX), AX        // string data
924         LEAQ    ret+16(FP), DX
925         JMP     runtime·aeshashbody(SB)
926
927 // AX: data
928 // CX: length
929 // DX: address to put return value
930 TEXT runtime·aeshashbody(SB),NOSPLIT,$0-0
931         MOVQ    h+8(FP), X6     // seed to low 64 bits of xmm6
932         PINSRQ  $1, CX, X6      // size to high 64 bits of xmm6
933         PSHUFHW $0, X6, X6      // replace size with its low 2 bytes repeated 4 times
934         MOVO    runtime·aeskeysched(SB), X7
935         CMPQ    CX, $16
936         JB      aes0to15
937         JE      aes16
938         CMPQ    CX, $32
939         JBE     aes17to32
940         CMPQ    CX, $64
941         JBE     aes33to64
942         CMPQ    CX, $128
943         JBE     aes65to128
944         JMP     aes129plus
945
946 aes0to15:
947         TESTQ   CX, CX
948         JE      aes0
949
950         ADDQ    $16, AX
951         TESTW   $0xff0, AX
952         JE      endofpage
953
954         // 16 bytes loaded at this address won't cross
955         // a page boundary, so we can load it directly.
956         MOVOU   -16(AX), X0
957         ADDQ    CX, CX
958         MOVQ    $masks<>(SB), AX
959         PAND    (AX)(CX*8), X0
960
961         // scramble 3 times
962         AESENC  X6, X0
963         AESENC  X7, X0
964         AESENC  X7, X0
965         MOVQ    X0, (DX)
966         RET
967
968 endofpage:
969         // address ends in 1111xxxx.  Might be up against
970         // a page boundary, so load ending at last byte.
971         // Then shift bytes down using pshufb.
972         MOVOU   -32(AX)(CX*1), X0
973         ADDQ    CX, CX
974         MOVQ    $shifts<>(SB), AX
975         PSHUFB  (AX)(CX*8), X0
976         AESENC  X6, X0
977         AESENC  X7, X0
978         AESENC  X7, X0
979         MOVQ    X0, (DX)
980         RET
981
982 aes0:
983         // return input seed
984         MOVQ    h+8(FP), AX
985         MOVQ    AX, (DX)
986         RET
987
988 aes16:
989         MOVOU   (AX), X0
990         AESENC  X6, X0
991         AESENC  X7, X0
992         AESENC  X7, X0
993         MOVQ    X0, (DX)
994         RET
995
996 aes17to32:
997         // load data to be hashed
998         MOVOU   (AX), X0
999         MOVOU   -16(AX)(CX*1), X1
1000
1001         // scramble 3 times
1002         AESENC  X6, X0
1003         AESENC  runtime·aeskeysched+16(SB), X1
1004         AESENC  X7, X0
1005         AESENC  X7, X1
1006         AESENC  X7, X0
1007         AESENC  X7, X1
1008
1009         // combine results
1010         PXOR    X1, X0
1011         MOVQ    X0, (DX)
1012         RET
1013
1014 aes33to64:
1015         MOVOU   (AX), X0
1016         MOVOU   16(AX), X1
1017         MOVOU   -32(AX)(CX*1), X2
1018         MOVOU   -16(AX)(CX*1), X3
1019         
1020         AESENC  X6, X0
1021         AESENC  runtime·aeskeysched+16(SB), X1
1022         AESENC  runtime·aeskeysched+32(SB), X2
1023         AESENC  runtime·aeskeysched+48(SB), X3
1024         AESENC  X7, X0
1025         AESENC  X7, X1
1026         AESENC  X7, X2
1027         AESENC  X7, X3
1028         AESENC  X7, X0
1029         AESENC  X7, X1
1030         AESENC  X7, X2
1031         AESENC  X7, X3
1032
1033         PXOR    X2, X0
1034         PXOR    X3, X1
1035         PXOR    X1, X0
1036         MOVQ    X0, (DX)
1037         RET
1038
1039 aes65to128:
1040         MOVOU   (AX), X0
1041         MOVOU   16(AX), X1
1042         MOVOU   32(AX), X2
1043         MOVOU   48(AX), X3
1044         MOVOU   -64(AX)(CX*1), X4
1045         MOVOU   -48(AX)(CX*1), X5
1046         MOVOU   -32(AX)(CX*1), X8
1047         MOVOU   -16(AX)(CX*1), X9
1048         
1049         AESENC  X6, X0
1050         AESENC  runtime·aeskeysched+16(SB), X1
1051         AESENC  runtime·aeskeysched+32(SB), X2
1052         AESENC  runtime·aeskeysched+48(SB), X3
1053         AESENC  runtime·aeskeysched+64(SB), X4
1054         AESENC  runtime·aeskeysched+80(SB), X5
1055         AESENC  runtime·aeskeysched+96(SB), X8
1056         AESENC  runtime·aeskeysched+112(SB), X9
1057         AESENC  X7, X0
1058         AESENC  X7, X1
1059         AESENC  X7, X2
1060         AESENC  X7, X3
1061         AESENC  X7, X4
1062         AESENC  X7, X5
1063         AESENC  X7, X8
1064         AESENC  X7, X9
1065         AESENC  X7, X0
1066         AESENC  X7, X1
1067         AESENC  X7, X2
1068         AESENC  X7, X3
1069         AESENC  X7, X4
1070         AESENC  X7, X5
1071         AESENC  X7, X8
1072         AESENC  X7, X9
1073
1074         PXOR    X4, X0
1075         PXOR    X5, X1
1076         PXOR    X8, X2
1077         PXOR    X9, X3
1078         PXOR    X2, X0
1079         PXOR    X3, X1
1080         PXOR    X1, X0
1081         MOVQ    X0, (DX)
1082         RET
1083
1084 aes129plus:
1085         // start with last (possibly overlapping) block
1086         MOVOU   -128(AX)(CX*1), X0
1087         MOVOU   -112(AX)(CX*1), X1
1088         MOVOU   -96(AX)(CX*1), X2
1089         MOVOU   -80(AX)(CX*1), X3
1090         MOVOU   -64(AX)(CX*1), X4
1091         MOVOU   -48(AX)(CX*1), X5
1092         MOVOU   -32(AX)(CX*1), X8
1093         MOVOU   -16(AX)(CX*1), X9
1094
1095         // scramble state once
1096         AESENC  X6, X0
1097         AESENC  runtime·aeskeysched+16(SB), X1
1098         AESENC  runtime·aeskeysched+32(SB), X2
1099         AESENC  runtime·aeskeysched+48(SB), X3
1100         AESENC  runtime·aeskeysched+64(SB), X4
1101         AESENC  runtime·aeskeysched+80(SB), X5
1102         AESENC  runtime·aeskeysched+96(SB), X8
1103         AESENC  runtime·aeskeysched+112(SB), X9
1104
1105         // compute number of remaining 128-byte blocks
1106         DECQ    CX
1107         SHRQ    $7, CX
1108         
1109 aesloop:
1110         // scramble state, xor in a block
1111         MOVOU   (AX), X10
1112         MOVOU   16(AX), X11
1113         MOVOU   32(AX), X12
1114         MOVOU   48(AX), X13
1115         AESENC  X10, X0
1116         AESENC  X11, X1
1117         AESENC  X12, X2
1118         AESENC  X13, X3
1119         MOVOU   64(AX), X10
1120         MOVOU   80(AX), X11
1121         MOVOU   96(AX), X12
1122         MOVOU   112(AX), X13
1123         AESENC  X10, X4
1124         AESENC  X11, X5
1125         AESENC  X12, X8
1126         AESENC  X13, X9
1127
1128         // scramble state
1129         AESENC  X7, X0
1130         AESENC  X7, X1
1131         AESENC  X7, X2
1132         AESENC  X7, X3
1133         AESENC  X7, X4
1134         AESENC  X7, X5
1135         AESENC  X7, X8
1136         AESENC  X7, X9
1137
1138         ADDQ    $128, AX
1139         DECQ    CX
1140         JNE     aesloop
1141
1142         // 2 more scrambles to finish
1143         AESENC  X7, X0
1144         AESENC  X7, X1
1145         AESENC  X7, X2
1146         AESENC  X7, X3
1147         AESENC  X7, X4
1148         AESENC  X7, X5
1149         AESENC  X7, X8
1150         AESENC  X7, X9
1151         AESENC  X7, X0
1152         AESENC  X7, X1
1153         AESENC  X7, X2
1154         AESENC  X7, X3
1155         AESENC  X7, X4
1156         AESENC  X7, X5
1157         AESENC  X7, X8
1158         AESENC  X7, X9
1159
1160         PXOR    X4, X0
1161         PXOR    X5, X1
1162         PXOR    X8, X2
1163         PXOR    X9, X3
1164         PXOR    X2, X0
1165         PXOR    X3, X1
1166         PXOR    X1, X0
1167         MOVQ    X0, (DX)
1168         RET
1169         
1170 TEXT runtime·aeshash32(SB),NOSPLIT,$0-24
1171         MOVQ    p+0(FP), AX     // ptr to data
1172         MOVQ    h+8(FP), X0     // seed
1173         PINSRD  $2, (AX), X0    // data
1174         AESENC  runtime·aeskeysched+0(SB), X0
1175         AESENC  runtime·aeskeysched+16(SB), X0
1176         AESENC  runtime·aeskeysched+32(SB), X0
1177         MOVQ    X0, ret+16(FP)
1178         RET
1179
1180 TEXT runtime·aeshash64(SB),NOSPLIT,$0-24
1181         MOVQ    p+0(FP), AX     // ptr to data
1182         MOVQ    h+8(FP), X0     // seed
1183         PINSRQ  $1, (AX), X0    // data
1184         AESENC  runtime·aeskeysched+0(SB), X0
1185         AESENC  runtime·aeskeysched+16(SB), X0
1186         AESENC  runtime·aeskeysched+32(SB), X0
1187         MOVQ    X0, ret+16(FP)
1188         RET
1189
1190 // simple mask to get rid of data in the high part of the register.
1191 DATA masks<>+0x00(SB)/8, $0x0000000000000000
1192 DATA masks<>+0x08(SB)/8, $0x0000000000000000
1193 DATA masks<>+0x10(SB)/8, $0x00000000000000ff
1194 DATA masks<>+0x18(SB)/8, $0x0000000000000000
1195 DATA masks<>+0x20(SB)/8, $0x000000000000ffff
1196 DATA masks<>+0x28(SB)/8, $0x0000000000000000
1197 DATA masks<>+0x30(SB)/8, $0x0000000000ffffff
1198 DATA masks<>+0x38(SB)/8, $0x0000000000000000
1199 DATA masks<>+0x40(SB)/8, $0x00000000ffffffff
1200 DATA masks<>+0x48(SB)/8, $0x0000000000000000
1201 DATA masks<>+0x50(SB)/8, $0x000000ffffffffff
1202 DATA masks<>+0x58(SB)/8, $0x0000000000000000
1203 DATA masks<>+0x60(SB)/8, $0x0000ffffffffffff
1204 DATA masks<>+0x68(SB)/8, $0x0000000000000000
1205 DATA masks<>+0x70(SB)/8, $0x00ffffffffffffff
1206 DATA masks<>+0x78(SB)/8, $0x0000000000000000
1207 DATA masks<>+0x80(SB)/8, $0xffffffffffffffff
1208 DATA masks<>+0x88(SB)/8, $0x0000000000000000
1209 DATA masks<>+0x90(SB)/8, $0xffffffffffffffff
1210 DATA masks<>+0x98(SB)/8, $0x00000000000000ff
1211 DATA masks<>+0xa0(SB)/8, $0xffffffffffffffff
1212 DATA masks<>+0xa8(SB)/8, $0x000000000000ffff
1213 DATA masks<>+0xb0(SB)/8, $0xffffffffffffffff
1214 DATA masks<>+0xb8(SB)/8, $0x0000000000ffffff
1215 DATA masks<>+0xc0(SB)/8, $0xffffffffffffffff
1216 DATA masks<>+0xc8(SB)/8, $0x00000000ffffffff
1217 DATA masks<>+0xd0(SB)/8, $0xffffffffffffffff
1218 DATA masks<>+0xd8(SB)/8, $0x000000ffffffffff
1219 DATA masks<>+0xe0(SB)/8, $0xffffffffffffffff
1220 DATA masks<>+0xe8(SB)/8, $0x0000ffffffffffff
1221 DATA masks<>+0xf0(SB)/8, $0xffffffffffffffff
1222 DATA masks<>+0xf8(SB)/8, $0x00ffffffffffffff
1223 GLOBL masks<>(SB),RODATA,$256
1224
1225 // these are arguments to pshufb.  They move data down from
1226 // the high bytes of the register to the low bytes of the register.
1227 // index is how many bytes to move.
1228 DATA shifts<>+0x00(SB)/8, $0x0000000000000000
1229 DATA shifts<>+0x08(SB)/8, $0x0000000000000000
1230 DATA shifts<>+0x10(SB)/8, $0xffffffffffffff0f
1231 DATA shifts<>+0x18(SB)/8, $0xffffffffffffffff
1232 DATA shifts<>+0x20(SB)/8, $0xffffffffffff0f0e
1233 DATA shifts<>+0x28(SB)/8, $0xffffffffffffffff
1234 DATA shifts<>+0x30(SB)/8, $0xffffffffff0f0e0d
1235 DATA shifts<>+0x38(SB)/8, $0xffffffffffffffff
1236 DATA shifts<>+0x40(SB)/8, $0xffffffff0f0e0d0c
1237 DATA shifts<>+0x48(SB)/8, $0xffffffffffffffff
1238 DATA shifts<>+0x50(SB)/8, $0xffffff0f0e0d0c0b
1239 DATA shifts<>+0x58(SB)/8, $0xffffffffffffffff
1240 DATA shifts<>+0x60(SB)/8, $0xffff0f0e0d0c0b0a
1241 DATA shifts<>+0x68(SB)/8, $0xffffffffffffffff
1242 DATA shifts<>+0x70(SB)/8, $0xff0f0e0d0c0b0a09
1243 DATA shifts<>+0x78(SB)/8, $0xffffffffffffffff
1244 DATA shifts<>+0x80(SB)/8, $0x0f0e0d0c0b0a0908
1245 DATA shifts<>+0x88(SB)/8, $0xffffffffffffffff
1246 DATA shifts<>+0x90(SB)/8, $0x0e0d0c0b0a090807
1247 DATA shifts<>+0x98(SB)/8, $0xffffffffffffff0f
1248 DATA shifts<>+0xa0(SB)/8, $0x0d0c0b0a09080706
1249 DATA shifts<>+0xa8(SB)/8, $0xffffffffffff0f0e
1250 DATA shifts<>+0xb0(SB)/8, $0x0c0b0a0908070605
1251 DATA shifts<>+0xb8(SB)/8, $0xffffffffff0f0e0d
1252 DATA shifts<>+0xc0(SB)/8, $0x0b0a090807060504
1253 DATA shifts<>+0xc8(SB)/8, $0xffffffff0f0e0d0c
1254 DATA shifts<>+0xd0(SB)/8, $0x0a09080706050403
1255 DATA shifts<>+0xd8(SB)/8, $0xffffff0f0e0d0c0b
1256 DATA shifts<>+0xe0(SB)/8, $0x0908070605040302
1257 DATA shifts<>+0xe8(SB)/8, $0xffff0f0e0d0c0b0a
1258 DATA shifts<>+0xf0(SB)/8, $0x0807060504030201
1259 DATA shifts<>+0xf8(SB)/8, $0xff0f0e0d0c0b0a09
1260 GLOBL shifts<>(SB),RODATA,$256
1261
1262 TEXT runtime·memeq(SB),NOSPLIT,$0-25
1263         MOVQ    a+0(FP), SI
1264         MOVQ    b+8(FP), DI
1265         MOVQ    size+16(FP), BX
1266         CALL    runtime·memeqbody(SB)
1267         MOVB    AX, ret+24(FP)
1268         RET
1269
1270 // memequal_varlen(a, b unsafe.Pointer) bool
1271 TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17
1272         MOVQ    a+0(FP), SI
1273         MOVQ    b+8(FP), DI
1274         CMPQ    SI, DI
1275         JEQ     eq
1276         MOVQ    8(DX), BX    // compiler stores size at offset 8 in the closure
1277         CALL    runtime·memeqbody(SB)
1278         MOVB    AX, ret+16(FP)
1279         RET
1280 eq:
1281         MOVB    $1, ret+16(FP)
1282         RET
1283
1284 // eqstring tests whether two strings are equal.
1285 // The compiler guarantees that strings passed
1286 // to eqstring have equal length.
1287 // See runtime_test.go:eqstring_generic for
1288 // equivalent Go code.
1289 TEXT runtime·eqstring(SB),NOSPLIT,$0-33
1290         MOVQ    s1str+0(FP), SI
1291         MOVQ    s2str+16(FP), DI
1292         CMPQ    SI, DI
1293         JEQ     eq
1294         MOVQ    s1len+8(FP), BX
1295         CALL    runtime·memeqbody(SB)
1296         MOVB    AX, v+32(FP)
1297         RET
1298 eq:
1299         MOVB    $1, v+32(FP)
1300         RET
1301
1302 // a in SI
1303 // b in DI
1304 // count in BX
1305 TEXT runtime·memeqbody(SB),NOSPLIT,$0-0
1306         XORQ    AX, AX
1307
1308         CMPQ    BX, $8
1309         JB      small
1310         
1311         // 64 bytes at a time using xmm registers
1312 hugeloop:
1313         CMPQ    BX, $64
1314         JB      bigloop
1315         MOVOU   (SI), X0
1316         MOVOU   (DI), X1
1317         MOVOU   16(SI), X2
1318         MOVOU   16(DI), X3
1319         MOVOU   32(SI), X4
1320         MOVOU   32(DI), X5
1321         MOVOU   48(SI), X6
1322         MOVOU   48(DI), X7
1323         PCMPEQB X1, X0
1324         PCMPEQB X3, X2
1325         PCMPEQB X5, X4
1326         PCMPEQB X7, X6
1327         PAND    X2, X0
1328         PAND    X6, X4
1329         PAND    X4, X0
1330         PMOVMSKB X0, DX
1331         ADDQ    $64, SI
1332         ADDQ    $64, DI
1333         SUBQ    $64, BX
1334         CMPL    DX, $0xffff
1335         JEQ     hugeloop
1336         RET
1337
1338         // 8 bytes at a time using 64-bit register
1339 bigloop:
1340         CMPQ    BX, $8
1341         JBE     leftover
1342         MOVQ    (SI), CX
1343         MOVQ    (DI), DX
1344         ADDQ    $8, SI
1345         ADDQ    $8, DI
1346         SUBQ    $8, BX
1347         CMPQ    CX, DX
1348         JEQ     bigloop
1349         RET
1350
1351         // remaining 0-8 bytes
1352 leftover:
1353         MOVQ    -8(SI)(BX*1), CX
1354         MOVQ    -8(DI)(BX*1), DX
1355         CMPQ    CX, DX
1356         SETEQ   AX
1357         RET
1358
1359 small:
1360         CMPQ    BX, $0
1361         JEQ     equal
1362
1363         LEAQ    0(BX*8), CX
1364         NEGQ    CX
1365
1366         CMPB    SI, $0xf8
1367         JA      si_high
1368
1369         // load at SI won't cross a page boundary.
1370         MOVQ    (SI), SI
1371         JMP     si_finish
1372 si_high:
1373         // address ends in 11111xxx.  Load up to bytes we want, move to correct position.
1374         MOVQ    -8(SI)(BX*1), SI
1375         SHRQ    CX, SI
1376 si_finish:
1377
1378         // same for DI.
1379         CMPB    DI, $0xf8
1380         JA      di_high
1381         MOVQ    (DI), DI
1382         JMP     di_finish
1383 di_high:
1384         MOVQ    -8(DI)(BX*1), DI
1385         SHRQ    CX, DI
1386 di_finish:
1387
1388         SUBQ    SI, DI
1389         SHLQ    CX, DI
1390 equal:
1391         SETEQ   AX
1392         RET
1393
1394 TEXT runtime·cmpstring(SB),NOSPLIT,$0-40
1395         MOVQ    s1_base+0(FP), SI
1396         MOVQ    s1_len+8(FP), BX
1397         MOVQ    s2_base+16(FP), DI
1398         MOVQ    s2_len+24(FP), DX
1399         CALL    runtime·cmpbody(SB)
1400         MOVQ    AX, ret+32(FP)
1401         RET
1402
1403 TEXT bytes·Compare(SB),NOSPLIT,$0-56
1404         MOVQ    s1+0(FP), SI
1405         MOVQ    s1+8(FP), BX
1406         MOVQ    s2+24(FP), DI
1407         MOVQ    s2+32(FP), DX
1408         CALL    runtime·cmpbody(SB)
1409         MOVQ    AX, res+48(FP)
1410         RET
1411
1412 // input:
1413 //   SI = a
1414 //   DI = b
1415 //   BX = alen
1416 //   DX = blen
1417 // output:
1418 //   AX = 1/0/-1
1419 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
1420         CMPQ    SI, DI
1421         JEQ     allsame
1422         CMPQ    BX, DX
1423         MOVQ    DX, R8
1424         CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
1425         CMPQ    R8, $8
1426         JB      small
1427
1428 loop:
1429         CMPQ    R8, $16
1430         JBE     _0through16
1431         MOVOU   (SI), X0
1432         MOVOU   (DI), X1
1433         PCMPEQB X0, X1
1434         PMOVMSKB X1, AX
1435         XORQ    $0xffff, AX     // convert EQ to NE
1436         JNE     diff16  // branch if at least one byte is not equal
1437         ADDQ    $16, SI
1438         ADDQ    $16, DI
1439         SUBQ    $16, R8
1440         JMP     loop
1441         
1442         // AX = bit mask of differences
1443 diff16:
1444         BSFQ    AX, BX  // index of first byte that differs
1445         XORQ    AX, AX
1446         MOVB    (SI)(BX*1), CX
1447         CMPB    CX, (DI)(BX*1)
1448         SETHI   AX
1449         LEAQ    -1(AX*2), AX    // convert 1/0 to +1/-1
1450         RET
1451
1452         // 0 through 16 bytes left, alen>=8, blen>=8
1453 _0through16:
1454         CMPQ    R8, $8
1455         JBE     _0through8
1456         MOVQ    (SI), AX
1457         MOVQ    (DI), CX
1458         CMPQ    AX, CX
1459         JNE     diff8
1460 _0through8:
1461         MOVQ    -8(SI)(R8*1), AX
1462         MOVQ    -8(DI)(R8*1), CX
1463         CMPQ    AX, CX
1464         JEQ     allsame
1465
1466         // AX and CX contain parts of a and b that differ.
1467 diff8:
1468         BSWAPQ  AX      // reverse order of bytes
1469         BSWAPQ  CX
1470         XORQ    AX, CX
1471         BSRQ    CX, CX  // index of highest bit difference
1472         SHRQ    CX, AX  // move a's bit to bottom
1473         ANDQ    $1, AX  // mask bit
1474         LEAQ    -1(AX*2), AX // 1/0 => +1/-1
1475         RET
1476
1477         // 0-7 bytes in common
1478 small:
1479         LEAQ    (R8*8), CX      // bytes left -> bits left
1480         NEGQ    CX              //  - bits lift (== 64 - bits left mod 64)
1481         JEQ     allsame
1482
1483         // load bytes of a into high bytes of AX
1484         CMPB    SI, $0xf8
1485         JA      si_high
1486         MOVQ    (SI), SI
1487         JMP     si_finish
1488 si_high:
1489         MOVQ    -8(SI)(R8*1), SI
1490         SHRQ    CX, SI
1491 si_finish:
1492         SHLQ    CX, SI
1493
1494         // load bytes of b in to high bytes of BX
1495         CMPB    DI, $0xf8
1496         JA      di_high
1497         MOVQ    (DI), DI
1498         JMP     di_finish
1499 di_high:
1500         MOVQ    -8(DI)(R8*1), DI
1501         SHRQ    CX, DI
1502 di_finish:
1503         SHLQ    CX, DI
1504
1505         BSWAPQ  SI      // reverse order of bytes
1506         BSWAPQ  DI
1507         XORQ    SI, DI  // find bit differences
1508         JEQ     allsame
1509         BSRQ    DI, CX  // index of highest bit difference
1510         SHRQ    CX, SI  // move a's bit to bottom
1511         ANDQ    $1, SI  // mask bit
1512         LEAQ    -1(SI*2), AX // 1/0 => +1/-1
1513         RET
1514
1515 allsame:
1516         XORQ    AX, AX
1517         XORQ    CX, CX
1518         CMPQ    BX, DX
1519         SETGT   AX      // 1 if alen > blen
1520         SETEQ   CX      // 1 if alen == blen
1521         LEAQ    -1(CX)(AX*2), AX        // 1,0,-1 result
1522         RET
1523
1524 TEXT bytes·IndexByte(SB),NOSPLIT,$0
1525         MOVQ s+0(FP), SI
1526         MOVQ s_len+8(FP), BX
1527         MOVB c+24(FP), AL
1528         CALL runtime·indexbytebody(SB)
1529         MOVQ AX, ret+32(FP)
1530         RET
1531
1532 TEXT strings·IndexByte(SB),NOSPLIT,$0
1533         MOVQ s+0(FP), SI
1534         MOVQ s_len+8(FP), BX
1535         MOVB c+16(FP), AL
1536         CALL runtime·indexbytebody(SB)
1537         MOVQ AX, ret+24(FP)
1538         RET
1539
1540 // input:
1541 //   SI: data
1542 //   BX: data len
1543 //   AL: byte sought
1544 // output:
1545 //   AX
1546 TEXT runtime·indexbytebody(SB),NOSPLIT,$0
1547         MOVQ SI, DI
1548
1549         CMPQ BX, $16
1550         JLT small
1551
1552         // round up to first 16-byte boundary
1553         TESTQ $15, SI
1554         JZ aligned
1555         MOVQ SI, CX
1556         ANDQ $~15, CX
1557         ADDQ $16, CX
1558
1559         // search the beginning
1560         SUBQ SI, CX
1561         REPN; SCASB
1562         JZ success
1563
1564 // DI is 16-byte aligned; get ready to search using SSE instructions
1565 aligned:
1566         // round down to last 16-byte boundary
1567         MOVQ BX, R11
1568         ADDQ SI, R11
1569         ANDQ $~15, R11
1570
1571         // shuffle X0 around so that each byte contains c
1572         MOVD AX, X0
1573         PUNPCKLBW X0, X0
1574         PUNPCKLBW X0, X0
1575         PSHUFL $0, X0, X0
1576         JMP condition
1577
1578 sse:
1579         // move the next 16-byte chunk of the buffer into X1
1580         MOVO (DI), X1
1581         // compare bytes in X0 to X1
1582         PCMPEQB X0, X1
1583         // take the top bit of each byte in X1 and put the result in DX
1584         PMOVMSKB X1, DX
1585         TESTL DX, DX
1586         JNZ ssesuccess
1587         ADDQ $16, DI
1588
1589 condition:
1590         CMPQ DI, R11
1591         JLT sse
1592
1593         // search the end
1594         MOVQ SI, CX
1595         ADDQ BX, CX
1596         SUBQ R11, CX
1597         // if CX == 0, the zero flag will be set and we'll end up
1598         // returning a false success
1599         JZ failure
1600         REPN; SCASB
1601         JZ success
1602
1603 failure:
1604         MOVQ $-1, AX
1605         RET
1606
1607 // handle for lengths < 16
1608 small:
1609         MOVQ BX, CX
1610         REPN; SCASB
1611         JZ success
1612         MOVQ $-1, AX
1613         RET
1614
1615 // we've found the chunk containing the byte
1616 // now just figure out which specific byte it is
1617 ssesuccess:
1618         // get the index of the least significant set bit
1619         BSFW DX, DX
1620         SUBQ SI, DI
1621         ADDQ DI, DX
1622         MOVQ DX, AX
1623         RET
1624
1625 success:
1626         SUBQ SI, DI
1627         SUBL $1, DI
1628         MOVQ DI, AX
1629         RET
1630
1631 TEXT bytes·Equal(SB),NOSPLIT,$0-49
1632         MOVQ    a_len+8(FP), BX
1633         MOVQ    b_len+32(FP), CX
1634         XORQ    AX, AX
1635         CMPQ    BX, CX
1636         JNE     eqret
1637         MOVQ    a+0(FP), SI
1638         MOVQ    b+24(FP), DI
1639         CALL    runtime·memeqbody(SB)
1640 eqret:
1641         MOVB    AX, ret+48(FP)
1642         RET
1643
1644 // A Duff's device for zeroing memory.
1645 // The compiler jumps to computed addresses within
1646 // this routine to zero chunks of memory.  Do not
1647 // change this code without also changing the code
1648 // in ../../cmd/6g/ggen.c:clearfat.
1649 // AX: zero
1650 // DI: ptr to memory to be zeroed
1651 // DI is updated as a side effect.
1652 TEXT runtime·duffzero(SB), NOSPLIT, $0-0
1653         STOSQ
1654         STOSQ
1655         STOSQ
1656         STOSQ
1657         STOSQ
1658         STOSQ
1659         STOSQ
1660         STOSQ
1661         STOSQ
1662         STOSQ
1663         STOSQ
1664         STOSQ
1665         STOSQ
1666         STOSQ
1667         STOSQ
1668         STOSQ
1669         STOSQ
1670         STOSQ
1671         STOSQ
1672         STOSQ
1673         STOSQ
1674         STOSQ
1675         STOSQ
1676         STOSQ
1677         STOSQ
1678         STOSQ
1679         STOSQ
1680         STOSQ
1681         STOSQ
1682         STOSQ
1683         STOSQ
1684         STOSQ
1685         STOSQ
1686         STOSQ
1687         STOSQ
1688         STOSQ
1689         STOSQ
1690         STOSQ
1691         STOSQ
1692         STOSQ
1693         STOSQ
1694         STOSQ
1695         STOSQ
1696         STOSQ
1697         STOSQ
1698         STOSQ
1699         STOSQ
1700         STOSQ
1701         STOSQ
1702         STOSQ
1703         STOSQ
1704         STOSQ
1705         STOSQ
1706         STOSQ
1707         STOSQ
1708         STOSQ
1709         STOSQ
1710         STOSQ
1711         STOSQ
1712         STOSQ
1713         STOSQ
1714         STOSQ
1715         STOSQ
1716         STOSQ
1717         STOSQ
1718         STOSQ
1719         STOSQ
1720         STOSQ
1721         STOSQ
1722         STOSQ
1723         STOSQ
1724         STOSQ
1725         STOSQ
1726         STOSQ
1727         STOSQ
1728         STOSQ
1729         STOSQ
1730         STOSQ
1731         STOSQ
1732         STOSQ
1733         STOSQ
1734         STOSQ
1735         STOSQ
1736         STOSQ
1737         STOSQ
1738         STOSQ
1739         STOSQ
1740         STOSQ
1741         STOSQ
1742         STOSQ
1743         STOSQ
1744         STOSQ
1745         STOSQ
1746         STOSQ
1747         STOSQ
1748         STOSQ
1749         STOSQ
1750         STOSQ
1751         STOSQ
1752         STOSQ
1753         STOSQ
1754         STOSQ
1755         STOSQ
1756         STOSQ
1757         STOSQ
1758         STOSQ
1759         STOSQ
1760         STOSQ
1761         STOSQ
1762         STOSQ
1763         STOSQ
1764         STOSQ
1765         STOSQ
1766         STOSQ
1767         STOSQ
1768         STOSQ
1769         STOSQ
1770         STOSQ
1771         STOSQ
1772         STOSQ
1773         STOSQ
1774         STOSQ
1775         STOSQ
1776         STOSQ
1777         STOSQ
1778         STOSQ
1779         STOSQ
1780         STOSQ
1781         RET
1782
1783 // A Duff's device for copying memory.
1784 // The compiler jumps to computed addresses within
1785 // this routine to copy chunks of memory.  Source
1786 // and destination must not overlap.  Do not
1787 // change this code without also changing the code
1788 // in ../../cmd/6g/cgen.c:sgen.
1789 // SI: ptr to source memory
1790 // DI: ptr to destination memory
1791 // SI and DI are updated as a side effect.
1792
1793 // NOTE: this is equivalent to a sequence of MOVSQ but
1794 // for some reason that is 3.5x slower than this code.
1795 // The STOSQ above seem fine, though.
1796 TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
1797         MOVQ    (SI),CX
1798         ADDQ    $8,SI
1799         MOVQ    CX,(DI)
1800         ADDQ    $8,DI
1801
1802         MOVQ    (SI),CX
1803         ADDQ    $8,SI
1804         MOVQ    CX,(DI)
1805         ADDQ    $8,DI
1806
1807         MOVQ    (SI),CX
1808         ADDQ    $8,SI
1809         MOVQ    CX,(DI)
1810         ADDQ    $8,DI
1811
1812         MOVQ    (SI),CX
1813         ADDQ    $8,SI
1814         MOVQ    CX,(DI)
1815         ADDQ    $8,DI
1816
1817         MOVQ    (SI),CX
1818         ADDQ    $8,SI
1819         MOVQ    CX,(DI)
1820         ADDQ    $8,DI
1821
1822         MOVQ    (SI),CX
1823         ADDQ    $8,SI
1824         MOVQ    CX,(DI)
1825         ADDQ    $8,DI
1826
1827         MOVQ    (SI),CX
1828         ADDQ    $8,SI
1829         MOVQ    CX,(DI)
1830         ADDQ    $8,DI
1831
1832         MOVQ    (SI),CX
1833         ADDQ    $8,SI
1834         MOVQ    CX,(DI)
1835         ADDQ    $8,DI
1836
1837         MOVQ    (SI),CX
1838         ADDQ    $8,SI
1839         MOVQ    CX,(DI)
1840         ADDQ    $8,DI
1841
1842         MOVQ    (SI),CX
1843         ADDQ    $8,SI
1844         MOVQ    CX,(DI)
1845         ADDQ    $8,DI
1846
1847         MOVQ    (SI),CX
1848         ADDQ    $8,SI
1849         MOVQ    CX,(DI)
1850         ADDQ    $8,DI
1851
1852         MOVQ    (SI),CX
1853         ADDQ    $8,SI
1854         MOVQ    CX,(DI)
1855         ADDQ    $8,DI
1856
1857         MOVQ    (SI),CX
1858         ADDQ    $8,SI
1859         MOVQ    CX,(DI)
1860         ADDQ    $8,DI
1861
1862         MOVQ    (SI),CX
1863         ADDQ    $8,SI
1864         MOVQ    CX,(DI)
1865         ADDQ    $8,DI
1866
1867         MOVQ    (SI),CX
1868         ADDQ    $8,SI
1869         MOVQ    CX,(DI)
1870         ADDQ    $8,DI
1871
1872         MOVQ    (SI),CX
1873         ADDQ    $8,SI
1874         MOVQ    CX,(DI)
1875         ADDQ    $8,DI
1876
1877         MOVQ    (SI),CX
1878         ADDQ    $8,SI
1879         MOVQ    CX,(DI)
1880         ADDQ    $8,DI
1881
1882         MOVQ    (SI),CX
1883         ADDQ    $8,SI
1884         MOVQ    CX,(DI)
1885         ADDQ    $8,DI
1886
1887         MOVQ    (SI),CX
1888         ADDQ    $8,SI
1889         MOVQ    CX,(DI)
1890         ADDQ    $8,DI
1891
1892         MOVQ    (SI),CX
1893         ADDQ    $8,SI
1894         MOVQ    CX,(DI)
1895         ADDQ    $8,DI
1896
1897         MOVQ    (SI),CX
1898         ADDQ    $8,SI
1899         MOVQ    CX,(DI)
1900         ADDQ    $8,DI
1901
1902         MOVQ    (SI),CX
1903         ADDQ    $8,SI
1904         MOVQ    CX,(DI)
1905         ADDQ    $8,DI
1906
1907         MOVQ    (SI),CX
1908         ADDQ    $8,SI
1909         MOVQ    CX,(DI)
1910         ADDQ    $8,DI
1911
1912         MOVQ    (SI),CX
1913         ADDQ    $8,SI
1914         MOVQ    CX,(DI)
1915         ADDQ    $8,DI
1916
1917         MOVQ    (SI),CX
1918         ADDQ    $8,SI
1919         MOVQ    CX,(DI)
1920         ADDQ    $8,DI
1921
1922         MOVQ    (SI),CX
1923         ADDQ    $8,SI
1924         MOVQ    CX,(DI)
1925         ADDQ    $8,DI
1926
1927         MOVQ    (SI),CX
1928         ADDQ    $8,SI
1929         MOVQ    CX,(DI)
1930         ADDQ    $8,DI
1931
1932         MOVQ    (SI),CX
1933         ADDQ    $8,SI
1934         MOVQ    CX,(DI)
1935         ADDQ    $8,DI
1936
1937         MOVQ    (SI),CX
1938         ADDQ    $8,SI
1939         MOVQ    CX,(DI)
1940         ADDQ    $8,DI
1941
1942         MOVQ    (SI),CX
1943         ADDQ    $8,SI
1944         MOVQ    CX,(DI)
1945         ADDQ    $8,DI
1946
1947         MOVQ    (SI),CX
1948         ADDQ    $8,SI
1949         MOVQ    CX,(DI)
1950         ADDQ    $8,DI
1951
1952         MOVQ    (SI),CX
1953         ADDQ    $8,SI
1954         MOVQ    CX,(DI)
1955         ADDQ    $8,DI
1956
1957         MOVQ    (SI),CX
1958         ADDQ    $8,SI
1959         MOVQ    CX,(DI)
1960         ADDQ    $8,DI
1961
1962         MOVQ    (SI),CX
1963         ADDQ    $8,SI
1964         MOVQ    CX,(DI)
1965         ADDQ    $8,DI
1966
1967         MOVQ    (SI),CX
1968         ADDQ    $8,SI
1969         MOVQ    CX,(DI)
1970         ADDQ    $8,DI
1971
1972         MOVQ    (SI),CX
1973         ADDQ    $8,SI
1974         MOVQ    CX,(DI)
1975         ADDQ    $8,DI
1976
1977         MOVQ    (SI),CX
1978         ADDQ    $8,SI
1979         MOVQ    CX,(DI)
1980         ADDQ    $8,DI
1981
1982         MOVQ    (SI),CX
1983         ADDQ    $8,SI
1984         MOVQ    CX,(DI)
1985         ADDQ    $8,DI
1986
1987         MOVQ    (SI),CX
1988         ADDQ    $8,SI
1989         MOVQ    CX,(DI)
1990         ADDQ    $8,DI
1991
1992         MOVQ    (SI),CX
1993         ADDQ    $8,SI
1994         MOVQ    CX,(DI)
1995         ADDQ    $8,DI
1996
1997         MOVQ    (SI),CX
1998         ADDQ    $8,SI
1999         MOVQ    CX,(DI)
2000         ADDQ    $8,DI
2001
2002         MOVQ    (SI),CX
2003         ADDQ    $8,SI
2004         MOVQ    CX,(DI)
2005         ADDQ    $8,DI
2006
2007         MOVQ    (SI),CX
2008         ADDQ    $8,SI
2009         MOVQ    CX,(DI)
2010         ADDQ    $8,DI
2011
2012         MOVQ    (SI),CX
2013         ADDQ    $8,SI
2014         MOVQ    CX,(DI)
2015         ADDQ    $8,DI
2016
2017         MOVQ    (SI),CX
2018         ADDQ    $8,SI
2019         MOVQ    CX,(DI)
2020         ADDQ    $8,DI
2021
2022         MOVQ    (SI),CX
2023         ADDQ    $8,SI
2024         MOVQ    CX,(DI)
2025         ADDQ    $8,DI
2026
2027         MOVQ    (SI),CX
2028         ADDQ    $8,SI
2029         MOVQ    CX,(DI)
2030         ADDQ    $8,DI
2031
2032         MOVQ    (SI),CX
2033         ADDQ    $8,SI
2034         MOVQ    CX,(DI)
2035         ADDQ    $8,DI
2036
2037         MOVQ    (SI),CX
2038         ADDQ    $8,SI
2039         MOVQ    CX,(DI)
2040         ADDQ    $8,DI
2041
2042         MOVQ    (SI),CX
2043         ADDQ    $8,SI
2044         MOVQ    CX,(DI)
2045         ADDQ    $8,DI
2046
2047         MOVQ    (SI),CX
2048         ADDQ    $8,SI
2049         MOVQ    CX,(DI)
2050         ADDQ    $8,DI
2051
2052         MOVQ    (SI),CX
2053         ADDQ    $8,SI
2054         MOVQ    CX,(DI)
2055         ADDQ    $8,DI
2056
2057         MOVQ    (SI),CX
2058         ADDQ    $8,SI
2059         MOVQ    CX,(DI)
2060         ADDQ    $8,DI
2061
2062         MOVQ    (SI),CX
2063         ADDQ    $8,SI
2064         MOVQ    CX,(DI)
2065         ADDQ    $8,DI
2066
2067         MOVQ    (SI),CX
2068         ADDQ    $8,SI
2069         MOVQ    CX,(DI)
2070         ADDQ    $8,DI
2071
2072         MOVQ    (SI),CX
2073         ADDQ    $8,SI
2074         MOVQ    CX,(DI)
2075         ADDQ    $8,DI
2076
2077         MOVQ    (SI),CX
2078         ADDQ    $8,SI
2079         MOVQ    CX,(DI)
2080         ADDQ    $8,DI
2081
2082         MOVQ    (SI),CX
2083         ADDQ    $8,SI
2084         MOVQ    CX,(DI)
2085         ADDQ    $8,DI
2086
2087         MOVQ    (SI),CX
2088         ADDQ    $8,SI
2089         MOVQ    CX,(DI)
2090         ADDQ    $8,DI
2091
2092         MOVQ    (SI),CX
2093         ADDQ    $8,SI
2094         MOVQ    CX,(DI)
2095         ADDQ    $8,DI
2096
2097         MOVQ    (SI),CX
2098         ADDQ    $8,SI
2099         MOVQ    CX,(DI)
2100         ADDQ    $8,DI
2101
2102         MOVQ    (SI),CX
2103         ADDQ    $8,SI
2104         MOVQ    CX,(DI)
2105         ADDQ    $8,DI
2106
2107         MOVQ    (SI),CX
2108         ADDQ    $8,SI
2109         MOVQ    CX,(DI)
2110         ADDQ    $8,DI
2111
2112         MOVQ    (SI),CX
2113         ADDQ    $8,SI
2114         MOVQ    CX,(DI)
2115         ADDQ    $8,DI
2116
2117         MOVQ    (SI),CX
2118         ADDQ    $8,SI
2119         MOVQ    CX,(DI)
2120         ADDQ    $8,DI
2121
2122         MOVQ    (SI),CX
2123         ADDQ    $8,SI
2124         MOVQ    CX,(DI)
2125         ADDQ    $8,DI
2126
2127         MOVQ    (SI),CX
2128         ADDQ    $8,SI
2129         MOVQ    CX,(DI)
2130         ADDQ    $8,DI
2131
2132         MOVQ    (SI),CX
2133         ADDQ    $8,SI
2134         MOVQ    CX,(DI)
2135         ADDQ    $8,DI
2136
2137         MOVQ    (SI),CX
2138         ADDQ    $8,SI
2139         MOVQ    CX,(DI)
2140         ADDQ    $8,DI
2141
2142         MOVQ    (SI),CX
2143         ADDQ    $8,SI
2144         MOVQ    CX,(DI)
2145         ADDQ    $8,DI
2146
2147         MOVQ    (SI),CX
2148         ADDQ    $8,SI
2149         MOVQ    CX,(DI)
2150         ADDQ    $8,DI
2151
2152         MOVQ    (SI),CX
2153         ADDQ    $8,SI
2154         MOVQ    CX,(DI)
2155         ADDQ    $8,DI
2156
2157         MOVQ    (SI),CX
2158         ADDQ    $8,SI
2159         MOVQ    CX,(DI)
2160         ADDQ    $8,DI
2161
2162         MOVQ    (SI),CX
2163         ADDQ    $8,SI
2164         MOVQ    CX,(DI)
2165         ADDQ    $8,DI
2166
2167         MOVQ    (SI),CX
2168         ADDQ    $8,SI
2169         MOVQ    CX,(DI)
2170         ADDQ    $8,DI
2171
2172         MOVQ    (SI),CX
2173         ADDQ    $8,SI
2174         MOVQ    CX,(DI)
2175         ADDQ    $8,DI
2176
2177         MOVQ    (SI),CX
2178         ADDQ    $8,SI
2179         MOVQ    CX,(DI)
2180         ADDQ    $8,DI
2181
2182         MOVQ    (SI),CX
2183         ADDQ    $8,SI
2184         MOVQ    CX,(DI)
2185         ADDQ    $8,DI
2186
2187         MOVQ    (SI),CX
2188         ADDQ    $8,SI
2189         MOVQ    CX,(DI)
2190         ADDQ    $8,DI
2191
2192         MOVQ    (SI),CX
2193         ADDQ    $8,SI
2194         MOVQ    CX,(DI)
2195         ADDQ    $8,DI
2196
2197         MOVQ    (SI),CX
2198         ADDQ    $8,SI
2199         MOVQ    CX,(DI)
2200         ADDQ    $8,DI
2201
2202         MOVQ    (SI),CX
2203         ADDQ    $8,SI
2204         MOVQ    CX,(DI)
2205         ADDQ    $8,DI
2206
2207         MOVQ    (SI),CX
2208         ADDQ    $8,SI
2209         MOVQ    CX,(DI)
2210         ADDQ    $8,DI
2211
2212         MOVQ    (SI),CX
2213         ADDQ    $8,SI
2214         MOVQ    CX,(DI)
2215         ADDQ    $8,DI
2216
2217         MOVQ    (SI),CX
2218         ADDQ    $8,SI
2219         MOVQ    CX,(DI)
2220         ADDQ    $8,DI
2221
2222         MOVQ    (SI),CX
2223         ADDQ    $8,SI
2224         MOVQ    CX,(DI)
2225         ADDQ    $8,DI
2226
2227         MOVQ    (SI),CX
2228         ADDQ    $8,SI
2229         MOVQ    CX,(DI)
2230         ADDQ    $8,DI
2231
2232         MOVQ    (SI),CX
2233         ADDQ    $8,SI
2234         MOVQ    CX,(DI)
2235         ADDQ    $8,DI
2236
2237         MOVQ    (SI),CX
2238         ADDQ    $8,SI
2239         MOVQ    CX,(DI)
2240         ADDQ    $8,DI
2241
2242         MOVQ    (SI),CX
2243         ADDQ    $8,SI
2244         MOVQ    CX,(DI)
2245         ADDQ    $8,DI
2246
2247         MOVQ    (SI),CX
2248         ADDQ    $8,SI
2249         MOVQ    CX,(DI)
2250         ADDQ    $8,DI
2251
2252         MOVQ    (SI),CX
2253         ADDQ    $8,SI
2254         MOVQ    CX,(DI)
2255         ADDQ    $8,DI
2256
2257         MOVQ    (SI),CX
2258         ADDQ    $8,SI
2259         MOVQ    CX,(DI)
2260         ADDQ    $8,DI
2261
2262         MOVQ    (SI),CX
2263         ADDQ    $8,SI
2264         MOVQ    CX,(DI)
2265         ADDQ    $8,DI
2266
2267         MOVQ    (SI),CX
2268         ADDQ    $8,SI
2269         MOVQ    CX,(DI)
2270         ADDQ    $8,DI
2271
2272         MOVQ    (SI),CX
2273         ADDQ    $8,SI
2274         MOVQ    CX,(DI)
2275         ADDQ    $8,DI
2276
2277         MOVQ    (SI),CX
2278         ADDQ    $8,SI
2279         MOVQ    CX,(DI)
2280         ADDQ    $8,DI
2281
2282         MOVQ    (SI),CX
2283         ADDQ    $8,SI
2284         MOVQ    CX,(DI)
2285         ADDQ    $8,DI
2286
2287         MOVQ    (SI),CX
2288         ADDQ    $8,SI
2289         MOVQ    CX,(DI)
2290         ADDQ    $8,DI
2291
2292         MOVQ    (SI),CX
2293         ADDQ    $8,SI
2294         MOVQ    CX,(DI)
2295         ADDQ    $8,DI
2296
2297         MOVQ    (SI),CX
2298         ADDQ    $8,SI
2299         MOVQ    CX,(DI)
2300         ADDQ    $8,DI
2301
2302         MOVQ    (SI),CX
2303         ADDQ    $8,SI
2304         MOVQ    CX,(DI)
2305         ADDQ    $8,DI
2306
2307         MOVQ    (SI),CX
2308         ADDQ    $8,SI
2309         MOVQ    CX,(DI)
2310         ADDQ    $8,DI
2311
2312         MOVQ    (SI),CX
2313         ADDQ    $8,SI
2314         MOVQ    CX,(DI)
2315         ADDQ    $8,DI
2316
2317         MOVQ    (SI),CX
2318         ADDQ    $8,SI
2319         MOVQ    CX,(DI)
2320         ADDQ    $8,DI
2321
2322         MOVQ    (SI),CX
2323         ADDQ    $8,SI
2324         MOVQ    CX,(DI)
2325         ADDQ    $8,DI
2326
2327         MOVQ    (SI),CX
2328         ADDQ    $8,SI
2329         MOVQ    CX,(DI)
2330         ADDQ    $8,DI
2331
2332         MOVQ    (SI),CX
2333         ADDQ    $8,SI
2334         MOVQ    CX,(DI)
2335         ADDQ    $8,DI
2336
2337         MOVQ    (SI),CX
2338         ADDQ    $8,SI
2339         MOVQ    CX,(DI)
2340         ADDQ    $8,DI
2341
2342         MOVQ    (SI),CX
2343         ADDQ    $8,SI
2344         MOVQ    CX,(DI)
2345         ADDQ    $8,DI
2346
2347         MOVQ    (SI),CX
2348         ADDQ    $8,SI
2349         MOVQ    CX,(DI)
2350         ADDQ    $8,DI
2351
2352         MOVQ    (SI),CX
2353         ADDQ    $8,SI
2354         MOVQ    CX,(DI)
2355         ADDQ    $8,DI
2356
2357         MOVQ    (SI),CX
2358         ADDQ    $8,SI
2359         MOVQ    CX,(DI)
2360         ADDQ    $8,DI
2361
2362         MOVQ    (SI),CX
2363         ADDQ    $8,SI
2364         MOVQ    CX,(DI)
2365         ADDQ    $8,DI
2366
2367         MOVQ    (SI),CX
2368         ADDQ    $8,SI
2369         MOVQ    CX,(DI)
2370         ADDQ    $8,DI
2371
2372         MOVQ    (SI),CX
2373         ADDQ    $8,SI
2374         MOVQ    CX,(DI)
2375         ADDQ    $8,DI
2376
2377         MOVQ    (SI),CX
2378         ADDQ    $8,SI
2379         MOVQ    CX,(DI)
2380         ADDQ    $8,DI
2381
2382         MOVQ    (SI),CX
2383         ADDQ    $8,SI
2384         MOVQ    CX,(DI)
2385         ADDQ    $8,DI
2386
2387         MOVQ    (SI),CX
2388         ADDQ    $8,SI
2389         MOVQ    CX,(DI)
2390         ADDQ    $8,DI
2391
2392         MOVQ    (SI),CX
2393         ADDQ    $8,SI
2394         MOVQ    CX,(DI)
2395         ADDQ    $8,DI
2396
2397         MOVQ    (SI),CX
2398         ADDQ    $8,SI
2399         MOVQ    CX,(DI)
2400         ADDQ    $8,DI
2401
2402         MOVQ    (SI),CX
2403         ADDQ    $8,SI
2404         MOVQ    CX,(DI)
2405         ADDQ    $8,DI
2406
2407         MOVQ    (SI),CX
2408         ADDQ    $8,SI
2409         MOVQ    CX,(DI)
2410         ADDQ    $8,DI
2411
2412         MOVQ    (SI),CX
2413         ADDQ    $8,SI
2414         MOVQ    CX,(DI)
2415         ADDQ    $8,DI
2416
2417         MOVQ    (SI),CX
2418         ADDQ    $8,SI
2419         MOVQ    CX,(DI)
2420         ADDQ    $8,DI
2421
2422         MOVQ    (SI),CX
2423         ADDQ    $8,SI
2424         MOVQ    CX,(DI)
2425         ADDQ    $8,DI
2426
2427         MOVQ    (SI),CX
2428         ADDQ    $8,SI
2429         MOVQ    CX,(DI)
2430         ADDQ    $8,DI
2431
2432         MOVQ    (SI),CX
2433         ADDQ    $8,SI
2434         MOVQ    CX,(DI)
2435         ADDQ    $8,DI
2436
2437         RET
2438
2439 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
2440         get_tls(CX)
2441         MOVQ    g(CX), AX
2442         MOVQ    g_m(AX), AX
2443         MOVL    m_fastrand(AX), DX
2444         ADDL    DX, DX
2445         MOVL    DX, BX
2446         XORL    $0x88888eef, DX
2447         CMOVLMI BX, DX
2448         MOVL    DX, m_fastrand(AX)
2449         MOVL    DX, ret+0(FP)
2450         RET
2451
2452 TEXT runtime·return0(SB), NOSPLIT, $0
2453         MOVL    $0, AX
2454         RET
2455
2456
2457 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
2458 // Must obey the gcc calling convention.
2459 TEXT _cgo_topofstack(SB),NOSPLIT,$0
2460         get_tls(CX)
2461         MOVQ    g(CX), AX
2462         MOVQ    g_m(AX), AX
2463         MOVQ    m_curg(AX), AX
2464         MOVQ    (g_stack+stack_hi)(AX), AX
2465         RET
2466
2467 // The top-most function running on a goroutine
2468 // returns to goexit+PCQuantum.
2469 TEXT runtime·goexit(SB),NOSPLIT,$0-0
2470         BYTE    $0x90   // NOP
2471         CALL    runtime·goexit1(SB)    // does not return
2472
2473 TEXT runtime·getg(SB),NOSPLIT,$0-8
2474         get_tls(CX)
2475         MOVQ    g(CX), AX
2476         MOVQ    AX, ret+0(FP)
2477         RET
2478
2479 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
2480         MOVQ    addr+0(FP), AX
2481         PREFETCHT0      (AX)
2482         RET
2483
2484 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
2485         MOVQ    addr+0(FP), AX
2486         PREFETCHT1      (AX)
2487         RET
2488
2489 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
2490         MOVQ    addr+0(FP), AX
2491         PREFETCHT2      (AX)
2492         RET
2493
2494 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
2495         MOVQ    addr+0(FP), AX
2496         PREFETCHNTA     (AX)
2497         RET