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