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