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