]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_amd64p32.s
[dev.power64] all: merge default into dev.power64
[gostls13.git] / src / runtime / asm_amd64p32.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         MOVL    SP, CX
14         SUBL    $128, SP                // plenty of scratch
15         ANDL    $~15, CX
16         MOVL    CX, SP
17
18         MOVL    AX, 16(SP)
19         MOVL    BX, 24(SP)
20         
21         // create istack out of the given (operating system) stack.
22         MOVL    $runtime·g0(SB), DI
23         LEAL    (-64*1024+104)(SP), BX
24         MOVL    BX, g_stackguard0(DI)
25         MOVL    BX, g_stackguard1(DI)
26         MOVL    BX, (g_stack+stack_lo)(DI)
27         MOVL    SP, (g_stack+stack_hi)(DI)
28
29         // find out information about the processor we're on
30         MOVQ    $0, AX
31         CPUID
32         CMPQ    AX, $0
33         JE      nocpuinfo
34         MOVQ    $1, AX
35         CPUID
36         MOVL    CX, runtime·cpuid_ecx(SB)
37         MOVL    DX, runtime·cpuid_edx(SB)
38 nocpuinfo:      
39         
40 needtls:
41         LEAL    runtime·tls0(SB), DI
42         CALL    runtime·settls(SB)
43
44         // store through it, to make sure it works
45         get_tls(BX)
46         MOVQ    $0x123, g(BX)
47         MOVQ    runtime·tls0(SB), AX
48         CMPQ    AX, $0x123
49         JEQ 2(PC)
50         MOVL    AX, 0   // abort
51 ok:
52         // set the per-goroutine and per-mach "registers"
53         get_tls(BX)
54         LEAL    runtime·g0(SB), CX
55         MOVL    CX, g(BX)
56         LEAL    runtime·m0(SB), AX
57
58         // save m->g0 = g0
59         MOVL    CX, m_g0(AX)
60         // save m0 to g0->m
61         MOVL    AX, g_m(CX)
62
63         CLD                             // convention is D is always left cleared
64         CALL    runtime·check(SB)
65
66         MOVL    16(SP), AX              // copy argc
67         MOVL    AX, 0(SP)
68         MOVL    24(SP), AX              // copy argv
69         MOVL    AX, 4(SP)
70         CALL    runtime·args(SB)
71         CALL    runtime·osinit(SB)
72         CALL    runtime·schedinit(SB)
73
74         // create a new goroutine to start program
75         MOVL    $runtime·main·f(SB), AX       // entry
76         MOVL    $0, 0(SP)
77         MOVL    AX, 4(SP)
78         CALL    runtime·newproc(SB)
79
80         // start this M
81         CALL    runtime·mstart(SB)
82
83         MOVL    $0xf1, 0xf1  // crash
84         RET
85
86 DATA    runtime·main·f+0(SB)/4,$runtime·main(SB)
87 GLOBL   runtime·main·f(SB),RODATA,$4
88
89 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
90         INT $3
91         RET
92
93 TEXT runtime·asminit(SB),NOSPLIT,$0-0
94         // No per-thread init.
95         RET
96
97 /*
98  *  go-routine
99  */
100
101 // void gosave(Gobuf*)
102 // save state in Gobuf; setjmp
103 TEXT runtime·gosave(SB), NOSPLIT, $0-4
104         MOVL    buf+0(FP), AX   // gobuf
105         LEAL    buf+0(FP), BX   // caller's SP
106         MOVL    BX, gobuf_sp(AX)
107         MOVL    0(SP), BX               // caller's PC
108         MOVL    BX, gobuf_pc(AX)
109         MOVL    $0, gobuf_ctxt(AX)
110         MOVQ    $0, gobuf_ret(AX)
111         get_tls(CX)
112         MOVL    g(CX), BX
113         MOVL    BX, gobuf_g(AX)
114         RET
115
116 // void gogo(Gobuf*)
117 // restore state from Gobuf; longjmp
118 TEXT runtime·gogo(SB), NOSPLIT, $0-4
119         MOVL    buf+0(FP), BX           // gobuf
120         MOVL    gobuf_g(BX), DX
121         MOVL    0(DX), CX               // make sure g != nil
122         get_tls(CX)
123         MOVL    DX, g(CX)
124         MOVL    gobuf_sp(BX), SP        // restore SP
125         MOVL    gobuf_ctxt(BX), DX
126         MOVQ    gobuf_ret(BX), AX
127         MOVL    $0, gobuf_sp(BX)        // clear to help garbage collector
128         MOVQ    $0, gobuf_ret(BX)
129         MOVL    $0, gobuf_ctxt(BX)
130         MOVL    gobuf_pc(BX), BX
131         JMP     BX
132
133 // func mcall(fn func(*g))
134 // Switch to m->g0's stack, call fn(g).
135 // Fn must never return.  It should gogo(&g->sched)
136 // to keep running g.
137 TEXT runtime·mcall(SB), NOSPLIT, $0-4
138         MOVL    fn+0(FP), DI
139         
140         get_tls(CX)
141         MOVL    g(CX), AX       // save state in g->sched
142         MOVL    0(SP), BX       // caller's PC
143         MOVL    BX, (g_sched+gobuf_pc)(AX)
144         LEAL    fn+0(FP), BX    // caller's SP
145         MOVL    BX, (g_sched+gobuf_sp)(AX)
146         MOVL    AX, (g_sched+gobuf_g)(AX)
147
148         // switch to m->g0 & its stack, call fn
149         MOVL    g(CX), BX
150         MOVL    g_m(BX), BX
151         MOVL    m_g0(BX), SI
152         CMPL    SI, AX  // if g == m->g0 call badmcall
153         JNE     3(PC)
154         MOVL    $runtime·badmcall(SB), AX
155         JMP     AX
156         MOVL    SI, g(CX)       // g = m->g0
157         MOVL    (g_sched+gobuf_sp)(SI), SP      // sp = m->g0->sched.sp
158         PUSHQ   AX
159         MOVL    DI, DX
160         MOVL    0(DI), DI
161         CALL    DI
162         POPQ    AX
163         MOVL    $runtime·badmcall2(SB), AX
164         JMP     AX
165         RET
166
167 // switchtoM is a dummy routine that onM leaves at the bottom
168 // of the G stack.  We need to distinguish the routine that
169 // lives at the bottom of the G stack from the one that lives
170 // at the top of the M stack because the one at the top of
171 // the M stack terminates the stack walk (see topofstack()).
172 TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
173         RET
174
175 // func onM_signalok(fn func())
176 TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
177         get_tls(CX)
178         MOVL    g(CX), AX       // AX = g
179         MOVL    g_m(AX), BX     // BX = m
180         MOVL    m_gsignal(BX), DX       // DX = gsignal
181         CMPL    AX, DX
182         JEQ     ongsignal
183         JMP     runtime·onM(SB)
184
185 ongsignal:
186         MOVL    fn+0(FP), DI    // DI = fn
187         MOVL    DI, DX
188         MOVL    0(DI), DI
189         CALL    DI
190         RET
191
192 // func onM(fn func())
193 TEXT runtime·onM(SB), NOSPLIT, $0-4
194         MOVL    fn+0(FP), DI    // DI = fn
195         get_tls(CX)
196         MOVL    g(CX), AX       // AX = g
197         MOVL    g_m(AX), BX     // BX = m
198
199         MOVL    m_g0(BX), DX    // DX = g0
200         CMPL    AX, DX
201         JEQ     onm
202
203         MOVL    m_curg(BX), R8
204         CMPL    AX, R8
205         JEQ     oncurg
206         
207         // Not g0, not curg. Must be gsignal, but that's not allowed.
208         // Hide call from linker nosplit analysis.
209         MOVL    $runtime·badonm(SB), AX
210         CALL    AX
211
212 oncurg:
213         // save our state in g->sched.  Pretend to
214         // be switchtoM if the G stack is scanned.
215         MOVL    $runtime·switchtoM(SB), SI
216         MOVL    SI, (g_sched+gobuf_pc)(AX)
217         MOVL    SP, (g_sched+gobuf_sp)(AX)
218         MOVL    AX, (g_sched+gobuf_g)(AX)
219
220         // switch to g0
221         MOVL    DX, g(CX)
222         MOVL    (g_sched+gobuf_sp)(DX), SP
223
224         // call target function
225         MOVL    DI, DX
226         MOVL    0(DI), DI
227         CALL    DI
228
229         // switch back to g
230         get_tls(CX)
231         MOVL    g(CX), AX
232         MOVL    g_m(AX), BX
233         MOVL    m_curg(BX), AX
234         MOVL    AX, g(CX)
235         MOVL    (g_sched+gobuf_sp)(AX), SP
236         MOVL    $0, (g_sched+gobuf_sp)(AX)
237         RET
238
239 onm:
240         // already on m stack, just call directly
241         MOVL    DI, DX
242         MOVL    0(DI), DI
243         CALL    DI
244         RET
245
246 /*
247  * support for morestack
248  */
249
250 // Called during function prolog when more stack is needed.
251 //
252 // The traceback routines see morestack on a g0 as being
253 // the top of a stack (for example, morestack calling newstack
254 // calling the scheduler calling newm calling gc), so we must
255 // record an argument size. For that purpose, it has no arguments.
256 TEXT runtime·morestack(SB),NOSPLIT,$0-0
257         get_tls(CX)
258         MOVL    g(CX), BX
259         MOVL    g_m(BX), BX
260
261         // Cannot grow scheduler stack (m->g0).
262         MOVL    m_g0(BX), SI
263         CMPL    g(CX), SI
264         JNE     2(PC)
265         MOVL    0, AX
266
267         // Cannot grow signal stack (m->gsignal).
268         MOVL    m_gsignal(BX), SI
269         CMPL    g(CX), SI
270         JNE     2(PC)
271         MOVL    0, AX
272
273         // Called from f.
274         // Set m->morebuf to f's caller.
275         MOVL    8(SP), AX       // f's caller's PC
276         MOVL    AX, (m_morebuf+gobuf_pc)(BX)
277         LEAL    16(SP), AX      // f's caller's SP
278         MOVL    AX, (m_morebuf+gobuf_sp)(BX)
279         get_tls(CX)
280         MOVL    g(CX), SI
281         MOVL    SI, (m_morebuf+gobuf_g)(BX)
282
283         // Set g->sched to context in f.
284         MOVL    0(SP), AX // f's PC
285         MOVL    AX, (g_sched+gobuf_pc)(SI)
286         MOVL    SI, (g_sched+gobuf_g)(SI)
287         LEAL    8(SP), AX // f's SP
288         MOVL    AX, (g_sched+gobuf_sp)(SI)
289         MOVL    DX, (g_sched+gobuf_ctxt)(SI)
290
291         // Call newstack on m->g0's stack.
292         MOVL    m_g0(BX), BX
293         MOVL    BX, g(CX)
294         MOVL    (g_sched+gobuf_sp)(BX), SP
295         CALL    runtime·newstack(SB)
296         MOVL    $0, 0x1003      // crash if newstack returns
297         RET
298
299 // morestack trampolines
300 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
301         MOVL    $0, DX
302         JMP     runtime·morestack(SB)
303
304 // reflectcall: call a function with the given argument list
305 // func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
306 // we don't have variable-sized frames, so we use a small number
307 // of constant-sized-frame functions to encode a few bits of size in the pc.
308 // Caution: ugly multiline assembly macros in your future!
309
310 #define DISPATCH(NAME,MAXSIZE)          \
311         CMPL    CX, $MAXSIZE;           \
312         JA      3(PC);                  \
313         MOVL    $NAME(SB), AX;          \
314         JMP     AX
315 // Note: can't just "JMP NAME(SB)" - bad inlining results.
316
317 TEXT ·reflectcall(SB), NOSPLIT, $0-16
318         MOVLQZX argsize+8(FP), CX
319         DISPATCH(runtime·call16, 16)
320         DISPATCH(runtime·call32, 32)
321         DISPATCH(runtime·call64, 64)
322         DISPATCH(runtime·call128, 128)
323         DISPATCH(runtime·call256, 256)
324         DISPATCH(runtime·call512, 512)
325         DISPATCH(runtime·call1024, 1024)
326         DISPATCH(runtime·call2048, 2048)
327         DISPATCH(runtime·call4096, 4096)
328         DISPATCH(runtime·call8192, 8192)
329         DISPATCH(runtime·call16384, 16384)
330         DISPATCH(runtime·call32768, 32768)
331         DISPATCH(runtime·call65536, 65536)
332         DISPATCH(runtime·call131072, 131072)
333         DISPATCH(runtime·call262144, 262144)
334         DISPATCH(runtime·call524288, 524288)
335         DISPATCH(runtime·call1048576, 1048576)
336         DISPATCH(runtime·call2097152, 2097152)
337         DISPATCH(runtime·call4194304, 4194304)
338         DISPATCH(runtime·call8388608, 8388608)
339         DISPATCH(runtime·call16777216, 16777216)
340         DISPATCH(runtime·call33554432, 33554432)
341         DISPATCH(runtime·call67108864, 67108864)
342         DISPATCH(runtime·call134217728, 134217728)
343         DISPATCH(runtime·call268435456, 268435456)
344         DISPATCH(runtime·call536870912, 536870912)
345         DISPATCH(runtime·call1073741824, 1073741824)
346         MOVL    $runtime·badreflectcall(SB), AX
347         JMP     AX
348
349 #define CALLFN(NAME,MAXSIZE)                    \
350 TEXT NAME(SB), WRAPPER, $MAXSIZE-16;            \
351         NO_LOCAL_POINTERS;                      \
352         /* copy arguments to stack */           \
353         MOVL    argptr+4(FP), SI;               \
354         MOVL    argsize+8(FP), CX;              \
355         MOVL    SP, DI;                         \
356         REP;MOVSB;                              \
357         /* call function */                     \
358         MOVL    f+0(FP), DX;                    \
359         MOVL    (DX), AX;                       \
360         CALL    AX;                             \
361         /* copy return values back */           \
362         MOVL    argptr+4(FP), DI;               \
363         MOVL    argsize+8(FP), CX;              \
364         MOVL    retoffset+12(FP), BX;           \
365         MOVL    SP, SI;                         \
366         ADDL    BX, DI;                         \
367         ADDL    BX, SI;                         \
368         SUBL    BX, CX;                         \
369         REP;MOVSB;                              \
370         RET
371
372 CALLFN(·call16, 16)
373 CALLFN(·call32, 32)
374 CALLFN(·call64, 64)
375 CALLFN(·call128, 128)
376 CALLFN(·call256, 256)
377 CALLFN(·call512, 512)
378 CALLFN(·call1024, 1024)
379 CALLFN(·call2048, 2048)
380 CALLFN(·call4096, 4096)
381 CALLFN(·call8192, 8192)
382 CALLFN(·call16384, 16384)
383 CALLFN(·call32768, 32768)
384 CALLFN(·call65536, 65536)
385 CALLFN(·call131072, 131072)
386 CALLFN(·call262144, 262144)
387 CALLFN(·call524288, 524288)
388 CALLFN(·call1048576, 1048576)
389 CALLFN(·call2097152, 2097152)
390 CALLFN(·call4194304, 4194304)
391 CALLFN(·call8388608, 8388608)
392 CALLFN(·call16777216, 16777216)
393 CALLFN(·call33554432, 33554432)
394 CALLFN(·call67108864, 67108864)
395 CALLFN(·call134217728, 134217728)
396 CALLFN(·call268435456, 268435456)
397 CALLFN(·call536870912, 536870912)
398 CALLFN(·call1073741824, 1073741824)
399
400 // bool cas(int32 *val, int32 old, int32 new)
401 // Atomically:
402 //      if(*val == old){
403 //              *val = new;
404 //              return 1;
405 //      } else
406 //              return 0;
407 TEXT runtime·cas(SB), NOSPLIT, $0-17
408         MOVL    ptr+0(FP), BX
409         MOVL    old+4(FP), AX
410         MOVL    new+8(FP), CX
411         LOCK
412         CMPXCHGL        CX, 0(BX)
413         JZ 4(PC)
414         MOVL    $0, AX
415         MOVB    AX, ret+16(FP)
416         RET
417         MOVL    $1, AX
418         MOVB    AX, ret+16(FP)
419         RET
420
421 TEXT runtime·casuintptr(SB), NOSPLIT, $0-17
422         JMP     runtime·cas(SB)
423
424 TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-12
425         JMP     runtime·atomicload(SB)
426
427 TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-12
428         JMP     runtime·atomicload(SB)
429
430 TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-12
431         JMP     runtime·atomicstore(SB)
432
433 // bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
434 // Atomically:
435 //      if(*val == *old){
436 //              *val = new;
437 //              return 1;
438 //      } else {
439 //              return 0;
440 //      }
441 TEXT runtime·cas64(SB), NOSPLIT, $0-25
442         MOVL    ptr+0(FP), BX
443         MOVQ    old+8(FP), AX
444         MOVQ    new+16(FP), CX
445         LOCK
446         CMPXCHGQ        CX, 0(BX)
447         JNZ     fail
448         MOVL    $1, AX
449         MOVB    AX, ret+24(FP)
450         RET
451 fail:
452         MOVL    $0, AX
453         MOVB    AX, ret+24(FP)
454         RET
455
456 // bool casp(void **val, void *old, void *new)
457 // Atomically:
458 //      if(*val == old){
459 //              *val = new;
460 //              return 1;
461 //      } else
462 //              return 0;
463 TEXT runtime·casp(SB), NOSPLIT, $0-17
464         MOVL    ptr+0(FP), BX
465         MOVL    old+4(FP), AX
466         MOVL    new+8(FP), CX
467         LOCK
468         CMPXCHGL        CX, 0(BX)
469         JZ 4(PC)
470         MOVL    $0, AX
471         MOVB    AX, ret+16(FP)
472         RET
473         MOVL    $1, AX
474         MOVB    AX, ret+16(FP)
475         RET
476
477 // uint32 xadd(uint32 volatile *val, int32 delta)
478 // Atomically:
479 //      *val += delta;
480 //      return *val;
481 TEXT runtime·xadd(SB), NOSPLIT, $0-12
482         MOVL    ptr+0(FP), BX
483         MOVL    delta+4(FP), AX
484         MOVL    AX, CX
485         LOCK
486         XADDL   AX, 0(BX)
487         ADDL    CX, AX
488         MOVL    AX, ret+8(FP)
489         RET
490
491 TEXT runtime·xadd64(SB), NOSPLIT, $0-24
492         MOVL    ptr+0(FP), BX
493         MOVQ    delta+8(FP), AX
494         MOVQ    AX, CX
495         LOCK
496         XADDQ   AX, 0(BX)
497         ADDQ    CX, AX
498         MOVQ    AX, ret+16(FP)
499         RET
500
501 TEXT runtime·xchg(SB), NOSPLIT, $0-12
502         MOVL    ptr+0(FP), BX
503         MOVL    new+4(FP), AX
504         XCHGL   AX, 0(BX)
505         MOVL    AX, ret+8(FP)
506         RET
507
508 TEXT runtime·xchg64(SB), NOSPLIT, $0-24
509         MOVL    ptr+0(FP), BX
510         MOVQ    new+8(FP), AX
511         XCHGQ   AX, 0(BX)
512         MOVQ    AX, ret+16(FP)
513         RET
514
515 TEXT runtime·xchgp(SB), NOSPLIT, $0-12
516         MOVL    ptr+0(FP), BX
517         MOVL    new+4(FP), AX
518         XCHGL   AX, 0(BX)
519         MOVL    AX, ret+8(FP)
520         RET
521
522 TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
523         JMP     runtime·xchg(SB)
524
525 TEXT runtime·procyield(SB),NOSPLIT,$0-0
526         MOVL    cycles+0(FP), AX
527 again:
528         PAUSE
529         SUBL    $1, AX
530         JNZ     again
531         RET
532
533 TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8
534         MOVL    ptr+0(FP), BX
535         MOVL    val+4(FP), AX
536         XCHGL   AX, 0(BX)
537         RET
538
539 TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
540         MOVL    ptr+0(FP), BX
541         MOVL    val+4(FP), AX
542         XCHGL   AX, 0(BX)
543         RET
544
545 TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
546         MOVL    ptr+0(FP), BX
547         MOVQ    val+8(FP), AX
548         XCHGQ   AX, 0(BX)
549         RET
550
551 // void runtime·atomicor8(byte volatile*, byte);
552 TEXT runtime·atomicor8(SB), NOSPLIT, $0-5
553         MOVL    ptr+0(FP), BX
554         MOVB    val+4(FP), AX
555         LOCK
556         ORB     AX, 0(BX)
557         RET
558
559 // void jmpdefer(fn, sp);
560 // called from deferreturn.
561 // 1. pop the caller
562 // 2. sub 5 bytes from the callers return
563 // 3. jmp to the argument
564 TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
565         MOVL    fv+0(FP), DX
566         MOVL    argp+4(FP), BX
567         LEAL    -8(BX), SP      // caller sp after CALL
568         SUBL    $5, (SP)        // return to CALL again
569         MOVL    0(DX), BX
570         JMP     BX      // but first run the deferred function
571
572 // asmcgocall(void(*fn)(void*), void *arg)
573 // Not implemented.
574 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
575         MOVL    0, AX
576         RET
577
578 // asmcgocall(void(*fn)(void*), void *arg)
579 // Not implemented.
580 TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
581         MOVL    0, AX
582         RET
583
584 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
585 // Not implemented.
586 TEXT runtime·cgocallback(SB),NOSPLIT,$0-12
587         MOVL    0, AX
588         RET
589
590 // void setg(G*); set g. for use by needm.
591 // Not implemented.
592 TEXT runtime·setg(SB), NOSPLIT, $0-4
593         MOVL    0, AX
594         RET
595
596 // check that SP is in range [g->stack.lo, g->stack.hi)
597 TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
598         get_tls(CX)
599         MOVL    g(CX), AX
600         CMPL    (g_stack+stack_hi)(AX), SP
601         JHI     2(PC)
602         MOVL    0, AX
603         CMPL    SP, (g_stack+stack_lo)(AX)
604         JHI     2(PC)
605         MOVL    0, AX
606         RET
607
608 TEXT runtime·memclr(SB),NOSPLIT,$0-8
609         MOVL    ptr+0(FP), DI
610         MOVL    n+4(FP), CX
611         MOVQ    CX, BX
612         ANDQ    $7, BX
613         SHRQ    $3, CX
614         MOVQ    $0, AX
615         CLD
616         REP
617         STOSQ
618         MOVQ    BX, CX
619         REP
620         STOSB
621         RET
622
623 TEXT runtime·getcallerpc(SB),NOSPLIT,$0-12
624         MOVL    argp+0(FP),AX           // addr of first arg
625         MOVL    -8(AX),AX               // get calling pc
626         MOVL    AX, ret+8(FP)
627         RET
628
629 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$0-12
630         MOVL    p+0(FP),AX              // addr of first arg
631         MOVL    -8(AX),AX               // get calling pc
632         MOVL    AX, ret+8(FP)
633         RET
634
635 TEXT runtime·setcallerpc(SB),NOSPLIT,$0-8
636         MOVL    argp+0(FP),AX           // addr of first arg
637         MOVL    pc+4(FP), BX            // pc to set
638         MOVQ    BX, -8(AX)              // set calling pc
639         RET
640
641 TEXT runtime·getcallersp(SB),NOSPLIT,$0-12
642         MOVL    argp+0(FP), AX
643         MOVL    AX, ret+8(FP)
644         RET
645
646 // func gogetcallersp(p unsafe.Pointer) uintptr
647 TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-12
648         MOVL    p+0(FP),AX              // addr of first arg
649         MOVL    AX, ret+8(FP)
650         RET
651
652 // int64 runtime·cputicks(void)
653 TEXT runtime·cputicks(SB),NOSPLIT,$0-0
654         RDTSC
655         SHLQ    $32, DX
656         ADDQ    DX, AX
657         MOVQ    AX, ret+0(FP)
658         RET
659
660 // hash function using AES hardware instructions
661 // For now, our one amd64p32 system (NaCl) does not
662 // support using AES instructions, so have not bothered to
663 // write the implementations. Can copy and adjust the ones
664 // in asm_amd64.s when the time comes.
665
666 TEXT runtime·aeshash(SB),NOSPLIT,$0-20
667         MOVL    AX, ret+16(FP)
668         RET
669
670 TEXT runtime·aeshashstr(SB),NOSPLIT,$0-20
671         MOVL    AX, ret+16(FP)
672         RET
673
674 TEXT runtime·aeshash32(SB),NOSPLIT,$0-20
675         MOVL    AX, ret+16(FP)
676         RET
677
678 TEXT runtime·aeshash64(SB),NOSPLIT,$0-20
679         MOVL    AX, ret+16(FP)
680         RET
681
682 TEXT runtime·memeq(SB),NOSPLIT,$0-17
683         MOVL    a+0(FP), SI
684         MOVL    b+4(FP), DI
685         MOVL    size+8(FP), BX
686         CALL    runtime·memeqbody(SB)
687         MOVB    AX, ret+16(FP)
688         RET
689
690 // eqstring tests whether two strings are equal.
691 // See runtime_test.go:eqstring_generic for
692 // equivalent Go code.
693 TEXT runtime·eqstring(SB),NOSPLIT,$0-17
694         MOVL    s1len+4(FP), AX
695         MOVL    s2len+12(FP), BX
696         CMPL    AX, BX
697         JNE     different
698         MOVL    s1str+0(FP), SI
699         MOVL    s2str+8(FP), DI
700         CMPL    SI, DI
701         JEQ     same
702         CALL    runtime·memeqbody(SB)
703         MOVB    AX, v+16(FP)
704         RET
705 same:
706         MOVB    $1, v+16(FP)
707         RET
708 different:
709         MOVB    $0, v+16(FP)
710         RET
711
712 // a in SI
713 // b in DI
714 // count in BX
715 TEXT runtime·memeqbody(SB),NOSPLIT,$0-0
716         XORQ    AX, AX
717
718         CMPQ    BX, $8
719         JB      small
720         
721         // 64 bytes at a time using xmm registers
722 hugeloop:
723         CMPQ    BX, $64
724         JB      bigloop
725         MOVOU   (SI), X0
726         MOVOU   (DI), X1
727         MOVOU   16(SI), X2
728         MOVOU   16(DI), X3
729         MOVOU   32(SI), X4
730         MOVOU   32(DI), X5
731         MOVOU   48(SI), X6
732         MOVOU   48(DI), X7
733         PCMPEQB X1, X0
734         PCMPEQB X3, X2
735         PCMPEQB X5, X4
736         PCMPEQB X7, X6
737         PAND    X2, X0
738         PAND    X6, X4
739         PAND    X4, X0
740         PMOVMSKB X0, DX
741         ADDQ    $64, SI
742         ADDQ    $64, DI
743         SUBQ    $64, BX
744         CMPL    DX, $0xffff
745         JEQ     hugeloop
746         RET
747
748         // 8 bytes at a time using 64-bit register
749 bigloop:
750         CMPQ    BX, $8
751         JBE     leftover
752         MOVQ    (SI), CX
753         MOVQ    (DI), DX
754         ADDQ    $8, SI
755         ADDQ    $8, DI
756         SUBQ    $8, BX
757         CMPQ    CX, DX
758         JEQ     bigloop
759         RET
760
761         // remaining 0-8 bytes
762 leftover:
763         ADDQ    BX, SI
764         ADDQ    BX, DI
765         MOVQ    -8(SI), CX
766         MOVQ    -8(DI), DX
767         CMPQ    CX, DX
768         SETEQ   AX
769         RET
770
771 small:
772         CMPQ    BX, $0
773         JEQ     equal
774
775         LEAQ    0(BX*8), CX
776         NEGQ    CX
777
778         CMPB    SI, $0xf8
779         JA      si_high
780
781         // load at SI won't cross a page boundary.
782         MOVQ    (SI), SI
783         JMP     si_finish
784 si_high:
785         // address ends in 11111xxx.  Load up to bytes we want, move to correct position.
786         MOVQ    BX, DX
787         ADDQ    SI, DX
788         MOVQ    -8(DX), SI
789         SHRQ    CX, SI
790 si_finish:
791
792         // same for DI.
793         CMPB    DI, $0xf8
794         JA      di_high
795         MOVQ    (DI), DI
796         JMP     di_finish
797 di_high:
798         MOVQ    BX, DX
799         ADDQ    DI, DX
800         MOVQ    -8(DX), DI
801         SHRQ    CX, DI
802 di_finish:
803
804         SUBQ    SI, DI
805         SHLQ    CX, DI
806 equal:
807         SETEQ   AX
808         RET
809
810 TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
811         MOVL    s1_base+0(FP), SI
812         MOVL    s1_len+4(FP), BX
813         MOVL    s2_base+8(FP), DI
814         MOVL    s2_len+12(FP), DX
815         CALL    runtime·cmpbody(SB)
816         MOVL    AX, ret+16(FP)
817         RET
818
819 TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28
820         MOVL    s1+0(FP), SI
821         MOVL    s1+4(FP), BX
822         MOVL    s2+12(FP), DI
823         MOVL    s2+16(FP), DX
824         CALL    runtime·cmpbody(SB)
825         MOVQ    AX, res+24(FP)
826         RET
827
828 // input:
829 //   SI = a
830 //   DI = b
831 //   BX = alen
832 //   DX = blen
833 // output:
834 //   AX = 1/0/-1
835 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
836         CMPQ    SI, DI
837         JEQ     allsame
838         CMPQ    BX, DX
839         MOVQ    DX, R8
840         CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
841         CMPQ    R8, $8
842         JB      small
843
844 loop:
845         CMPQ    R8, $16
846         JBE     _0through16
847         MOVOU   (SI), X0
848         MOVOU   (DI), X1
849         PCMPEQB X0, X1
850         PMOVMSKB X1, AX
851         XORQ    $0xffff, AX     // convert EQ to NE
852         JNE     diff16  // branch if at least one byte is not equal
853         ADDQ    $16, SI
854         ADDQ    $16, DI
855         SUBQ    $16, R8
856         JMP     loop
857         
858         // AX = bit mask of differences
859 diff16:
860         BSFQ    AX, BX  // index of first byte that differs
861         XORQ    AX, AX
862         ADDQ    BX, SI
863         MOVB    (SI), CX
864         ADDQ    BX, DI
865         CMPB    CX, (DI)
866         SETHI   AX
867         LEAQ    -1(AX*2), AX    // convert 1/0 to +1/-1
868         RET
869
870         // 0 through 16 bytes left, alen>=8, blen>=8
871 _0through16:
872         CMPQ    R8, $8
873         JBE     _0through8
874         MOVQ    (SI), AX
875         MOVQ    (DI), CX
876         CMPQ    AX, CX
877         JNE     diff8
878 _0through8:
879         ADDQ    R8, SI
880         ADDQ    R8, DI
881         MOVQ    -8(SI), AX
882         MOVQ    -8(DI), CX
883         CMPQ    AX, CX
884         JEQ     allsame
885
886         // AX and CX contain parts of a and b that differ.
887 diff8:
888         BSWAPQ  AX      // reverse order of bytes
889         BSWAPQ  CX
890         XORQ    AX, CX
891         BSRQ    CX, CX  // index of highest bit difference
892         SHRQ    CX, AX  // move a's bit to bottom
893         ANDQ    $1, AX  // mask bit
894         LEAQ    -1(AX*2), AX // 1/0 => +1/-1
895         RET
896
897         // 0-7 bytes in common
898 small:
899         LEAQ    (R8*8), CX      // bytes left -> bits left
900         NEGQ    CX              //  - bits lift (== 64 - bits left mod 64)
901         JEQ     allsame
902
903         // load bytes of a into high bytes of AX
904         CMPB    SI, $0xf8
905         JA      si_high
906         MOVQ    (SI), SI
907         JMP     si_finish
908 si_high:
909         ADDQ    R8, SI
910         MOVQ    -8(SI), SI
911         SHRQ    CX, SI
912 si_finish:
913         SHLQ    CX, SI
914
915         // load bytes of b in to high bytes of BX
916         CMPB    DI, $0xf8
917         JA      di_high
918         MOVQ    (DI), DI
919         JMP     di_finish
920 di_high:
921         ADDQ    R8, DI
922         MOVQ    -8(DI), DI
923         SHRQ    CX, DI
924 di_finish:
925         SHLQ    CX, DI
926
927         BSWAPQ  SI      // reverse order of bytes
928         BSWAPQ  DI
929         XORQ    SI, DI  // find bit differences
930         JEQ     allsame
931         BSRQ    DI, CX  // index of highest bit difference
932         SHRQ    CX, SI  // move a's bit to bottom
933         ANDQ    $1, SI  // mask bit
934         LEAQ    -1(SI*2), AX // 1/0 => +1/-1
935         RET
936
937 allsame:
938         XORQ    AX, AX
939         XORQ    CX, CX
940         CMPQ    BX, DX
941         SETGT   AX      // 1 if alen > blen
942         SETEQ   CX      // 1 if alen == blen
943         LEAQ    -1(CX)(AX*2), AX        // 1,0,-1 result
944         RET
945
946 TEXT bytes·IndexByte(SB),NOSPLIT,$0
947         MOVL s+0(FP), SI
948         MOVL s_len+4(FP), BX
949         MOVB c+12(FP), AL
950         CALL runtime·indexbytebody(SB)
951         MOVL AX, ret+16(FP)
952         RET
953
954 TEXT strings·IndexByte(SB),NOSPLIT,$0
955         MOVL s+0(FP), SI
956         MOVL s_len+4(FP), BX
957         MOVB c+8(FP), AL
958         CALL runtime·indexbytebody(SB)
959         MOVL AX, ret+16(FP)
960         RET
961
962 // input:
963 //   SI: data
964 //   BX: data len
965 //   AL: byte sought
966 // output:
967 //   AX
968 TEXT runtime·indexbytebody(SB),NOSPLIT,$0
969         MOVL SI, DI
970
971         CMPL BX, $16
972         JLT small
973
974         // round up to first 16-byte boundary
975         TESTL $15, SI
976         JZ aligned
977         MOVL SI, CX
978         ANDL $~15, CX
979         ADDL $16, CX
980
981         // search the beginning
982         SUBL SI, CX
983         REPN; SCASB
984         JZ success
985
986 // DI is 16-byte aligned; get ready to search using SSE instructions
987 aligned:
988         // round down to last 16-byte boundary
989         MOVL BX, R11
990         ADDL SI, R11
991         ANDL $~15, R11
992
993         // shuffle X0 around so that each byte contains c
994         MOVD AX, X0
995         PUNPCKLBW X0, X0
996         PUNPCKLBW X0, X0
997         PSHUFL $0, X0, X0
998         JMP condition
999
1000 sse:
1001         // move the next 16-byte chunk of the buffer into X1
1002         MOVO (DI), X1
1003         // compare bytes in X0 to X1
1004         PCMPEQB X0, X1
1005         // take the top bit of each byte in X1 and put the result in DX
1006         PMOVMSKB X1, DX
1007         TESTL DX, DX
1008         JNZ ssesuccess
1009         ADDL $16, DI
1010
1011 condition:
1012         CMPL DI, R11
1013         JLT sse
1014
1015         // search the end
1016         MOVL SI, CX
1017         ADDL BX, CX
1018         SUBL R11, CX
1019         // if CX == 0, the zero flag will be set and we'll end up
1020         // returning a false success
1021         JZ failure
1022         REPN; SCASB
1023         JZ success
1024
1025 failure:
1026         MOVL $-1, AX
1027         RET
1028
1029 // handle for lengths < 16
1030 small:
1031         MOVL BX, CX
1032         REPN; SCASB
1033         JZ success
1034         MOVL $-1, AX
1035         RET
1036
1037 // we've found the chunk containing the byte
1038 // now just figure out which specific byte it is
1039 ssesuccess:
1040         // get the index of the least significant set bit
1041         BSFW DX, DX
1042         SUBL SI, DI
1043         ADDL DI, DX
1044         MOVL DX, AX
1045         RET
1046
1047 success:
1048         SUBL SI, DI
1049         SUBL $1, DI
1050         MOVL DI, AX
1051         RET
1052
1053 TEXT bytes·Equal(SB),NOSPLIT,$0-25
1054         MOVL    a_len+4(FP), BX
1055         MOVL    b_len+16(FP), CX
1056         XORL    AX, AX
1057         CMPL    BX, CX
1058         JNE     eqret
1059         MOVL    a+0(FP), SI
1060         MOVL    b+12(FP), DI
1061         CALL    runtime·memeqbody(SB)
1062 eqret:
1063         MOVB    AX, ret+24(FP)
1064         RET
1065
1066 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
1067         get_tls(CX)
1068         MOVL    g(CX), AX
1069         MOVL    g_m(AX), AX
1070         MOVL    m_fastrand(AX), DX
1071         ADDL    DX, DX
1072         MOVL    DX, BX
1073         XORL    $0x88888eef, DX
1074         CMOVLMI BX, DX
1075         MOVL    DX, m_fastrand(AX)
1076         MOVL    DX, ret+0(FP)
1077         RET
1078
1079 TEXT runtime·return0(SB), NOSPLIT, $0
1080         MOVL    $0, AX
1081         RET
1082
1083 // The top-most function running on a goroutine
1084 // returns to goexit+PCQuantum.
1085 TEXT runtime·goexit(SB),NOSPLIT,$0-0
1086         BYTE    $0x90   // NOP
1087         CALL    runtime·goexit1(SB)    // does not return