]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_386.s
runtime/cgo: store M for C-created thread in pthread key
[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 "go_asm.h"
6 #include "go_tls.h"
7 #include "funcdata.h"
8 #include "textflag.h"
9
10 // _rt0_386 is common startup code for most 386 systems when using
11 // internal linking. This is the entry point for the program from the
12 // kernel for an ordinary -buildmode=exe program. The stack holds the
13 // number of arguments and the C-style argv.
14 TEXT _rt0_386(SB),NOSPLIT,$8
15         MOVL    8(SP), AX       // argc
16         LEAL    12(SP), BX      // argv
17         MOVL    AX, 0(SP)
18         MOVL    BX, 4(SP)
19         JMP     runtime·rt0_go(SB)
20
21 // _rt0_386_lib is common startup code for most 386 systems when
22 // using -buildmode=c-archive or -buildmode=c-shared. The linker will
23 // arrange to invoke this function as a global constructor (for
24 // c-archive) or when the shared library is loaded (for c-shared).
25 // We expect argc and argv to be passed on the stack following the
26 // usual C ABI.
27 TEXT _rt0_386_lib(SB),NOSPLIT,$0
28         PUSHL   BP
29         MOVL    SP, BP
30         PUSHL   BX
31         PUSHL   SI
32         PUSHL   DI
33
34         MOVL    8(BP), AX
35         MOVL    AX, _rt0_386_lib_argc<>(SB)
36         MOVL    12(BP), AX
37         MOVL    AX, _rt0_386_lib_argv<>(SB)
38
39         // Synchronous initialization.
40         CALL    runtime·libpreinit(SB)
41
42         SUBL    $8, SP
43
44         // Create a new thread to do the runtime initialization.
45         MOVL    _cgo_sys_thread_create(SB), AX
46         TESTL   AX, AX
47         JZ      nocgo
48
49         // Align stack to call C function.
50         // We moved SP to BP above, but BP was clobbered by the libpreinit call.
51         MOVL    SP, BP
52         ANDL    $~15, SP
53
54         MOVL    $_rt0_386_lib_go(SB), BX
55         MOVL    BX, 0(SP)
56         MOVL    $0, 4(SP)
57
58         CALL    AX
59
60         MOVL    BP, SP
61
62         JMP     restore
63
64 nocgo:
65         MOVL    $0x800000, 0(SP)                    // stacksize = 8192KB
66         MOVL    $_rt0_386_lib_go(SB), AX
67         MOVL    AX, 4(SP)                           // fn
68         CALL    runtime·newosproc0(SB)
69
70 restore:
71         ADDL    $8, SP
72         POPL    DI
73         POPL    SI
74         POPL    BX
75         POPL    BP
76         RET
77
78 // _rt0_386_lib_go initializes the Go runtime.
79 // This is started in a separate thread by _rt0_386_lib.
80 TEXT _rt0_386_lib_go(SB),NOSPLIT,$8
81         MOVL    _rt0_386_lib_argc<>(SB), AX
82         MOVL    AX, 0(SP)
83         MOVL    _rt0_386_lib_argv<>(SB), AX
84         MOVL    AX, 4(SP)
85         JMP     runtime·rt0_go(SB)
86
87 DATA _rt0_386_lib_argc<>(SB)/4, $0
88 GLOBL _rt0_386_lib_argc<>(SB),NOPTR, $4
89 DATA _rt0_386_lib_argv<>(SB)/4, $0
90 GLOBL _rt0_386_lib_argv<>(SB),NOPTR, $4
91
92 TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
93         // Copy arguments forward on an even stack.
94         // Users of this function jump to it, they don't call it.
95         MOVL    0(SP), AX
96         MOVL    4(SP), BX
97         SUBL    $128, SP                // plenty of scratch
98         ANDL    $~15, SP
99         MOVL    AX, 120(SP)             // save argc, argv away
100         MOVL    BX, 124(SP)
101
102         // set default stack bounds.
103         // _cgo_init may update stackguard.
104         MOVL    $runtime·g0(SB), BP
105         LEAL    (-64*1024+104)(SP), BX
106         MOVL    BX, g_stackguard0(BP)
107         MOVL    BX, g_stackguard1(BP)
108         MOVL    BX, (g_stack+stack_lo)(BP)
109         MOVL    SP, (g_stack+stack_hi)(BP)
110
111         // find out information about the processor we're on
112         // first see if CPUID instruction is supported.
113         PUSHFL
114         PUSHFL
115         XORL    $(1<<21), 0(SP) // flip ID bit
116         POPFL
117         PUSHFL
118         POPL    AX
119         XORL    0(SP), AX
120         POPFL   // restore EFLAGS
121         TESTL   $(1<<21), AX
122         JNE     has_cpuid
123
124 bad_proc: // show that the program requires MMX.
125         MOVL    $2, 0(SP)
126         MOVL    $bad_proc_msg<>(SB), 4(SP)
127         MOVL    $0x3d, 8(SP)
128         CALL    runtime·write(SB)
129         MOVL    $1, 0(SP)
130         CALL    runtime·exit(SB)
131         CALL    runtime·abort(SB)
132
133 has_cpuid:
134         MOVL    $0, AX
135         CPUID
136         MOVL    AX, SI
137         CMPL    AX, $0
138         JE      nocpuinfo
139
140         CMPL    BX, $0x756E6547  // "Genu"
141         JNE     notintel
142         CMPL    DX, $0x49656E69  // "ineI"
143         JNE     notintel
144         CMPL    CX, $0x6C65746E  // "ntel"
145         JNE     notintel
146         MOVB    $1, runtime·isIntel(SB)
147 notintel:
148
149         // Load EAX=1 cpuid flags
150         MOVL    $1, AX
151         CPUID
152         MOVL    CX, DI // Move to global variable clobbers CX when generating PIC
153         MOVL    AX, runtime·processorVersionInfo(SB)
154
155         // Check for MMX support
156         TESTL   $(1<<23), DX // MMX
157         JZ      bad_proc
158
159 nocpuinfo:
160         // if there is an _cgo_init, call it to let it
161         // initialize and to set up GS.  if not,
162         // we set up GS ourselves.
163         MOVL    _cgo_init(SB), AX
164         TESTL   AX, AX
165         JZ      needtls
166 #ifdef GOOS_android
167         // arg 4: TLS base, stored in slot 0 (Android's TLS_SLOT_SELF).
168         // Compensate for tls_g (+8).
169         MOVL    -8(TLS), BX
170         MOVL    BX, 12(SP)
171         MOVL    $runtime·tls_g(SB), 8(SP)      // arg 3: &tls_g
172 #else
173         MOVL    $0, BX
174         MOVL    BX, 12(SP)      // arg 4: not used when using platform's TLS
175 #ifdef GOOS_windows
176         MOVL    $runtime·tls_g(SB), 8(SP)      // arg 3: &tls_g
177 #else
178         MOVL    BX, 8(SP)       // arg 3: not used when using platform's TLS
179 #endif
180 #endif
181         MOVL    $setg_gcc<>(SB), BX
182         MOVL    BX, 4(SP)       // arg 2: setg_gcc
183         MOVL    BP, 0(SP)       // arg 1: g0
184         CALL    AX
185
186         // update stackguard after _cgo_init
187         MOVL    $runtime·g0(SB), CX
188         MOVL    (g_stack+stack_lo)(CX), AX
189         ADDL    $const__StackGuard, AX
190         MOVL    AX, g_stackguard0(CX)
191         MOVL    AX, g_stackguard1(CX)
192
193 #ifndef GOOS_windows
194         // skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
195         JMP ok
196 #endif
197 needtls:
198 #ifdef GOOS_openbsd
199         // skip runtime·ldt0setup(SB) and tls test on OpenBSD in all cases
200         JMP     ok
201 #endif
202 #ifdef GOOS_plan9
203         // skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
204         JMP     ok
205 #endif
206
207         // set up %gs
208         CALL    ldt0setup<>(SB)
209
210         // store through it, to make sure it works
211         get_tls(BX)
212         MOVL    $0x123, g(BX)
213         MOVL    runtime·m0+m_tls(SB), AX
214         CMPL    AX, $0x123
215         JEQ     ok
216         MOVL    AX, 0   // abort
217 ok:
218         // set up m and g "registers"
219         get_tls(BX)
220         LEAL    runtime·g0(SB), DX
221         MOVL    DX, g(BX)
222         LEAL    runtime·m0(SB), AX
223
224         // save m->g0 = g0
225         MOVL    DX, m_g0(AX)
226         // save g0->m = m0
227         MOVL    AX, g_m(DX)
228
229         CALL    runtime·emptyfunc(SB)  // fault if stack check is wrong
230
231         // convention is D is always cleared
232         CLD
233
234         CALL    runtime·check(SB)
235
236         // saved argc, argv
237         MOVL    120(SP), AX
238         MOVL    AX, 0(SP)
239         MOVL    124(SP), AX
240         MOVL    AX, 4(SP)
241         CALL    runtime·args(SB)
242         CALL    runtime·osinit(SB)
243         CALL    runtime·schedinit(SB)
244
245         // create a new goroutine to start program
246         PUSHL   $runtime·mainPC(SB)    // entry
247         CALL    runtime·newproc(SB)
248         POPL    AX
249
250         // start this M
251         CALL    runtime·mstart(SB)
252
253         CALL    runtime·abort(SB)
254         RET
255
256 DATA    bad_proc_msg<>+0x00(SB)/61, $"This program can only be run on processors with MMX support.\n"
257 GLOBL   bad_proc_msg<>(SB), RODATA, $61
258
259 DATA    runtime·mainPC+0(SB)/4,$runtime·main(SB)
260 GLOBL   runtime·mainPC(SB),RODATA,$4
261
262 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
263         INT $3
264         RET
265
266 TEXT runtime·asminit(SB),NOSPLIT,$0-0
267         // Linux and MinGW start the FPU in extended double precision.
268         // Other operating systems use double precision.
269         // Change to double precision to match them,
270         // and to match other hardware that only has double.
271         FLDCW   runtime·controlWord64(SB)
272         RET
273
274 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
275         CALL    runtime·mstart0(SB)
276         RET // not reached
277
278 /*
279  *  go-routine
280  */
281
282 // void gogo(Gobuf*)
283 // restore state from Gobuf; longjmp
284 TEXT runtime·gogo(SB), NOSPLIT, $0-4
285         MOVL    buf+0(FP), BX           // gobuf
286         MOVL    gobuf_g(BX), DX
287         MOVL    0(DX), CX               // make sure g != nil
288         JMP     gogo<>(SB)
289
290 TEXT gogo<>(SB), NOSPLIT, $0
291         get_tls(CX)
292         MOVL    DX, g(CX)
293         MOVL    gobuf_sp(BX), SP        // restore SP
294         MOVL    gobuf_ret(BX), AX
295         MOVL    gobuf_ctxt(BX), DX
296         MOVL    $0, gobuf_sp(BX)        // clear to help garbage collector
297         MOVL    $0, gobuf_ret(BX)
298         MOVL    $0, gobuf_ctxt(BX)
299         MOVL    gobuf_pc(BX), BX
300         JMP     BX
301
302 // func mcall(fn func(*g))
303 // Switch to m->g0's stack, call fn(g).
304 // Fn must never return. It should gogo(&g->sched)
305 // to keep running g.
306 TEXT runtime·mcall(SB), NOSPLIT, $0-4
307         MOVL    fn+0(FP), DI
308
309         get_tls(DX)
310         MOVL    g(DX), AX       // save state in g->sched
311         MOVL    0(SP), BX       // caller's PC
312         MOVL    BX, (g_sched+gobuf_pc)(AX)
313         LEAL    fn+0(FP), BX    // caller's SP
314         MOVL    BX, (g_sched+gobuf_sp)(AX)
315
316         // switch to m->g0 & its stack, call fn
317         MOVL    g(DX), BX
318         MOVL    g_m(BX), BX
319         MOVL    m_g0(BX), SI
320         CMPL    SI, AX  // if g == m->g0 call badmcall
321         JNE     3(PC)
322         MOVL    $runtime·badmcall(SB), AX
323         JMP     AX
324         MOVL    SI, g(DX)       // g = m->g0
325         MOVL    (g_sched+gobuf_sp)(SI), SP      // sp = m->g0->sched.sp
326         PUSHL   AX
327         MOVL    DI, DX
328         MOVL    0(DI), DI
329         CALL    DI
330         POPL    AX
331         MOVL    $runtime·badmcall2(SB), AX
332         JMP     AX
333         RET
334
335 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
336 // of the G stack. We need to distinguish the routine that
337 // lives at the bottom of the G stack from the one that lives
338 // at the top of the system stack because the one at the top of
339 // the system stack terminates the stack walk (see topofstack()).
340 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
341         RET
342
343 // func systemstack(fn func())
344 TEXT runtime·systemstack(SB), NOSPLIT, $0-4
345         MOVL    fn+0(FP), DI    // DI = fn
346         get_tls(CX)
347         MOVL    g(CX), AX       // AX = g
348         MOVL    g_m(AX), BX     // BX = m
349
350         CMPL    AX, m_gsignal(BX)
351         JEQ     noswitch
352
353         MOVL    m_g0(BX), DX    // DX = g0
354         CMPL    AX, DX
355         JEQ     noswitch
356
357         CMPL    AX, m_curg(BX)
358         JNE     bad
359
360         // switch stacks
361         // save our state in g->sched. Pretend to
362         // be systemstack_switch if the G stack is scanned.
363         CALL    gosave_systemstack_switch<>(SB)
364
365         // switch to g0
366         get_tls(CX)
367         MOVL    DX, g(CX)
368         MOVL    (g_sched+gobuf_sp)(DX), BX
369         MOVL    BX, SP
370
371         // call target function
372         MOVL    DI, DX
373         MOVL    0(DI), DI
374         CALL    DI
375
376         // switch back to g
377         get_tls(CX)
378         MOVL    g(CX), AX
379         MOVL    g_m(AX), BX
380         MOVL    m_curg(BX), AX
381         MOVL    AX, g(CX)
382         MOVL    (g_sched+gobuf_sp)(AX), SP
383         MOVL    $0, (g_sched+gobuf_sp)(AX)
384         RET
385
386 noswitch:
387         // already on system stack; tail call the function
388         // Using a tail call here cleans up tracebacks since we won't stop
389         // at an intermediate systemstack.
390         MOVL    DI, DX
391         MOVL    0(DI), DI
392         JMP     DI
393
394 bad:
395         // Bad: g is not gsignal, not g0, not curg. What is it?
396         // Hide call from linker nosplit analysis.
397         MOVL    $runtime·badsystemstack(SB), AX
398         CALL    AX
399         INT     $3
400
401 /*
402  * support for morestack
403  */
404
405 // Called during function prolog when more stack is needed.
406 //
407 // The traceback routines see morestack on a g0 as being
408 // the top of a stack (for example, morestack calling newstack
409 // calling the scheduler calling newm calling gc), so we must
410 // record an argument size. For that purpose, it has no arguments.
411 TEXT runtime·morestack(SB),NOSPLIT,$0-0
412         // Cannot grow scheduler stack (m->g0).
413         get_tls(CX)
414         MOVL    g(CX), BX
415         MOVL    g_m(BX), BX
416         MOVL    m_g0(BX), SI
417         CMPL    g(CX), SI
418         JNE     3(PC)
419         CALL    runtime·badmorestackg0(SB)
420         CALL    runtime·abort(SB)
421
422         // Cannot grow signal stack.
423         MOVL    m_gsignal(BX), SI
424         CMPL    g(CX), SI
425         JNE     3(PC)
426         CALL    runtime·badmorestackgsignal(SB)
427         CALL    runtime·abort(SB)
428
429         // Called from f.
430         // Set m->morebuf to f's caller.
431         NOP     SP      // tell vet SP changed - stop checking offsets
432         MOVL    4(SP), DI       // f's caller's PC
433         MOVL    DI, (m_morebuf+gobuf_pc)(BX)
434         LEAL    8(SP), CX       // f's caller's SP
435         MOVL    CX, (m_morebuf+gobuf_sp)(BX)
436         get_tls(CX)
437         MOVL    g(CX), SI
438         MOVL    SI, (m_morebuf+gobuf_g)(BX)
439
440         // Set g->sched to context in f.
441         MOVL    0(SP), AX       // f's PC
442         MOVL    AX, (g_sched+gobuf_pc)(SI)
443         LEAL    4(SP), AX       // f's SP
444         MOVL    AX, (g_sched+gobuf_sp)(SI)
445         MOVL    DX, (g_sched+gobuf_ctxt)(SI)
446
447         // Call newstack on m->g0's stack.
448         MOVL    m_g0(BX), BP
449         MOVL    BP, g(CX)
450         MOVL    (g_sched+gobuf_sp)(BP), AX
451         MOVL    -4(AX), BX      // fault if CALL would, before smashing SP
452         MOVL    AX, SP
453         CALL    runtime·newstack(SB)
454         CALL    runtime·abort(SB)      // crash if newstack returns
455         RET
456
457 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
458         MOVL    $0, DX
459         JMP runtime·morestack(SB)
460
461 // reflectcall: call a function with the given argument list
462 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
463 // we don't have variable-sized frames, so we use a small number
464 // of constant-sized-frame functions to encode a few bits of size in the pc.
465 // Caution: ugly multiline assembly macros in your future!
466
467 #define DISPATCH(NAME,MAXSIZE)          \
468         CMPL    CX, $MAXSIZE;           \
469         JA      3(PC);                  \
470         MOVL    $NAME(SB), AX;          \
471         JMP     AX
472 // Note: can't just "JMP NAME(SB)" - bad inlining results.
473
474 TEXT ·reflectcall(SB), NOSPLIT, $0-28
475         MOVL    frameSize+20(FP), CX
476         DISPATCH(runtime·call16, 16)
477         DISPATCH(runtime·call32, 32)
478         DISPATCH(runtime·call64, 64)
479         DISPATCH(runtime·call128, 128)
480         DISPATCH(runtime·call256, 256)
481         DISPATCH(runtime·call512, 512)
482         DISPATCH(runtime·call1024, 1024)
483         DISPATCH(runtime·call2048, 2048)
484         DISPATCH(runtime·call4096, 4096)
485         DISPATCH(runtime·call8192, 8192)
486         DISPATCH(runtime·call16384, 16384)
487         DISPATCH(runtime·call32768, 32768)
488         DISPATCH(runtime·call65536, 65536)
489         DISPATCH(runtime·call131072, 131072)
490         DISPATCH(runtime·call262144, 262144)
491         DISPATCH(runtime·call524288, 524288)
492         DISPATCH(runtime·call1048576, 1048576)
493         DISPATCH(runtime·call2097152, 2097152)
494         DISPATCH(runtime·call4194304, 4194304)
495         DISPATCH(runtime·call8388608, 8388608)
496         DISPATCH(runtime·call16777216, 16777216)
497         DISPATCH(runtime·call33554432, 33554432)
498         DISPATCH(runtime·call67108864, 67108864)
499         DISPATCH(runtime·call134217728, 134217728)
500         DISPATCH(runtime·call268435456, 268435456)
501         DISPATCH(runtime·call536870912, 536870912)
502         DISPATCH(runtime·call1073741824, 1073741824)
503         MOVL    $runtime·badreflectcall(SB), AX
504         JMP     AX
505
506 #define CALLFN(NAME,MAXSIZE)                    \
507 TEXT NAME(SB), WRAPPER, $MAXSIZE-28;            \
508         NO_LOCAL_POINTERS;                      \
509         /* copy arguments to stack */           \
510         MOVL    stackArgs+8(FP), SI;            \
511         MOVL    stackArgsSize+12(FP), CX;               \
512         MOVL    SP, DI;                         \
513         REP;MOVSB;                              \
514         /* call function */                     \
515         MOVL    f+4(FP), DX;                    \
516         MOVL    (DX), AX;                       \
517         PCDATA  $PCDATA_StackMapIndex, $0;      \
518         CALL    AX;                             \
519         /* copy return values back */           \
520         MOVL    stackArgsType+0(FP), DX;                \
521         MOVL    stackArgs+8(FP), DI;            \
522         MOVL    stackArgsSize+12(FP), CX;               \
523         MOVL    stackRetOffset+16(FP), BX;              \
524         MOVL    SP, SI;                         \
525         ADDL    BX, DI;                         \
526         ADDL    BX, SI;                         \
527         SUBL    BX, CX;                         \
528         CALL    callRet<>(SB);                  \
529         RET
530
531 // callRet copies return values back at the end of call*. This is a
532 // separate function so it can allocate stack space for the arguments
533 // to reflectcallmove. It does not follow the Go ABI; it expects its
534 // arguments in registers.
535 TEXT callRet<>(SB), NOSPLIT, $20-0
536         MOVL    DX, 0(SP)
537         MOVL    DI, 4(SP)
538         MOVL    SI, 8(SP)
539         MOVL    CX, 12(SP)
540         MOVL    $0, 16(SP)
541         CALL    runtime·reflectcallmove(SB)
542         RET
543
544 CALLFN(·call16, 16)
545 CALLFN(·call32, 32)
546 CALLFN(·call64, 64)
547 CALLFN(·call128, 128)
548 CALLFN(·call256, 256)
549 CALLFN(·call512, 512)
550 CALLFN(·call1024, 1024)
551 CALLFN(·call2048, 2048)
552 CALLFN(·call4096, 4096)
553 CALLFN(·call8192, 8192)
554 CALLFN(·call16384, 16384)
555 CALLFN(·call32768, 32768)
556 CALLFN(·call65536, 65536)
557 CALLFN(·call131072, 131072)
558 CALLFN(·call262144, 262144)
559 CALLFN(·call524288, 524288)
560 CALLFN(·call1048576, 1048576)
561 CALLFN(·call2097152, 2097152)
562 CALLFN(·call4194304, 4194304)
563 CALLFN(·call8388608, 8388608)
564 CALLFN(·call16777216, 16777216)
565 CALLFN(·call33554432, 33554432)
566 CALLFN(·call67108864, 67108864)
567 CALLFN(·call134217728, 134217728)
568 CALLFN(·call268435456, 268435456)
569 CALLFN(·call536870912, 536870912)
570 CALLFN(·call1073741824, 1073741824)
571
572 TEXT runtime·procyield(SB),NOSPLIT,$0-0
573         MOVL    cycles+0(FP), AX
574 again:
575         PAUSE
576         SUBL    $1, AX
577         JNZ     again
578         RET
579
580 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
581         // Stores are already ordered on x86, so this is just a
582         // compile barrier.
583         RET
584
585 // Save state of caller into g->sched,
586 // but using fake PC from systemstack_switch.
587 // Must only be called from functions with no locals ($0)
588 // or else unwinding from systemstack_switch is incorrect.
589 TEXT gosave_systemstack_switch<>(SB),NOSPLIT,$0
590         PUSHL   AX
591         PUSHL   BX
592         get_tls(BX)
593         MOVL    g(BX), BX
594         LEAL    arg+0(FP), AX
595         MOVL    AX, (g_sched+gobuf_sp)(BX)
596         MOVL    $runtime·systemstack_switch(SB), AX
597         MOVL    AX, (g_sched+gobuf_pc)(BX)
598         MOVL    $0, (g_sched+gobuf_ret)(BX)
599         // Assert ctxt is zero. See func save.
600         MOVL    (g_sched+gobuf_ctxt)(BX), AX
601         TESTL   AX, AX
602         JZ      2(PC)
603         CALL    runtime·abort(SB)
604         POPL    BX
605         POPL    AX
606         RET
607
608 // func asmcgocall_no_g(fn, arg unsafe.Pointer)
609 // Call fn(arg) aligned appropriately for the gcc ABI.
610 // Called on a system stack, and there may be no g yet (during needm).
611 TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-8
612         MOVL    fn+0(FP), AX
613         MOVL    arg+4(FP), BX
614         MOVL    SP, DX
615         SUBL    $32, SP
616         ANDL    $~15, SP        // alignment, perhaps unnecessary
617         MOVL    DX, 8(SP)       // save old SP
618         MOVL    BX, 0(SP)       // first argument in x86-32 ABI
619         CALL    AX
620         MOVL    8(SP), DX
621         MOVL    DX, SP
622         RET
623
624 // func asmcgocall(fn, arg unsafe.Pointer) int32
625 // Call fn(arg) on the scheduler stack,
626 // aligned appropriately for the gcc ABI.
627 // See cgocall.go for more details.
628 TEXT ·asmcgocall(SB),NOSPLIT,$0-12
629         MOVL    fn+0(FP), AX
630         MOVL    arg+4(FP), BX
631
632         MOVL    SP, DX
633
634         // Figure out if we need to switch to m->g0 stack.
635         // We get called to create new OS threads too, and those
636         // come in on the m->g0 stack already. Or we might already
637         // be on the m->gsignal stack.
638         get_tls(CX)
639         MOVL    g(CX), DI
640         CMPL    DI, $0
641         JEQ     nosave  // Don't even have a G yet.
642         MOVL    g_m(DI), BP
643         CMPL    DI, m_gsignal(BP)
644         JEQ     noswitch
645         MOVL    m_g0(BP), SI
646         CMPL    DI, SI
647         JEQ     noswitch
648         CALL    gosave_systemstack_switch<>(SB)
649         get_tls(CX)
650         MOVL    SI, g(CX)
651         MOVL    (g_sched+gobuf_sp)(SI), SP
652
653 noswitch:
654         // Now on a scheduling stack (a pthread-created stack).
655         SUBL    $32, SP
656         ANDL    $~15, SP        // alignment, perhaps unnecessary
657         MOVL    DI, 8(SP)       // save g
658         MOVL    (g_stack+stack_hi)(DI), DI
659         SUBL    DX, DI
660         MOVL    DI, 4(SP)       // save depth in stack (can't just save SP, as stack might be copied during a callback)
661         MOVL    BX, 0(SP)       // first argument in x86-32 ABI
662         CALL    AX
663
664         // Restore registers, g, stack pointer.
665         get_tls(CX)
666         MOVL    8(SP), DI
667         MOVL    (g_stack+stack_hi)(DI), SI
668         SUBL    4(SP), SI
669         MOVL    DI, g(CX)
670         MOVL    SI, SP
671
672         MOVL    AX, ret+8(FP)
673         RET
674 nosave:
675         // Now on a scheduling stack (a pthread-created stack).
676         SUBL    $32, SP
677         ANDL    $~15, SP        // alignment, perhaps unnecessary
678         MOVL    DX, 4(SP)       // save original stack pointer
679         MOVL    BX, 0(SP)       // first argument in x86-32 ABI
680         CALL    AX
681
682         MOVL    4(SP), CX       // restore original stack pointer
683         MOVL    CX, SP
684         MOVL    AX, ret+8(FP)
685         RET
686
687 // cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
688 // See cgocall.go for more details.
689 TEXT ·cgocallback(SB),NOSPLIT,$12-12  // Frame size must match commented places below
690         NO_LOCAL_POINTERS
691
692         // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
693         // It is used to dropm while thread is exiting.
694         MOVL    fn+0(FP), AX
695         CMPL    AX, $0
696         JNE     loadg
697         // Restore the g from frame.
698         get_tls(CX)
699         MOVL    frame+4(FP), BX
700         MOVL    BX, g(CX)
701         JMP     dropm
702
703 loadg:
704         // If g is nil, Go did not create the current thread,
705         // or if this thread never called into Go on pthread platforms.
706         // Call needm to obtain one for temporary use.
707         // In this case, we're running on the thread stack, so there's
708         // lots of space, but the linker doesn't know. Hide the call from
709         // the linker analysis by using an indirect call through AX.
710         get_tls(CX)
711 #ifdef GOOS_windows
712         MOVL    $0, BP
713         CMPL    CX, $0
714         JEQ     2(PC) // TODO
715 #endif
716         MOVL    g(CX), BP
717         CMPL    BP, $0
718         JEQ     needm
719         MOVL    g_m(BP), BP
720         MOVL    BP, savedm-4(SP) // saved copy of oldm
721         JMP     havem
722 needm:
723         MOVL    $runtime·needAndBindM(SB), AX
724         CALL    AX
725         MOVL    $0, savedm-4(SP)
726         get_tls(CX)
727         MOVL    g(CX), BP
728         MOVL    g_m(BP), BP
729
730         // Set m->sched.sp = SP, so that if a panic happens
731         // during the function we are about to execute, it will
732         // have a valid SP to run on the g0 stack.
733         // The next few lines (after the havem label)
734         // will save this SP onto the stack and then write
735         // the same SP back to m->sched.sp. That seems redundant,
736         // but if an unrecovered panic happens, unwindm will
737         // restore the g->sched.sp from the stack location
738         // and then systemstack will try to use it. If we don't set it here,
739         // that restored SP will be uninitialized (typically 0) and
740         // will not be usable.
741         MOVL    m_g0(BP), SI
742         MOVL    SP, (g_sched+gobuf_sp)(SI)
743
744 havem:
745         // Now there's a valid m, and we're running on its m->g0.
746         // Save current m->g0->sched.sp on stack and then set it to SP.
747         // Save current sp in m->g0->sched.sp in preparation for
748         // switch back to m->curg stack.
749         // NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
750         MOVL    m_g0(BP), SI
751         MOVL    (g_sched+gobuf_sp)(SI), AX
752         MOVL    AX, 0(SP)
753         MOVL    SP, (g_sched+gobuf_sp)(SI)
754
755         // Switch to m->curg stack and call runtime.cgocallbackg.
756         // Because we are taking over the execution of m->curg
757         // but *not* resuming what had been running, we need to
758         // save that information (m->curg->sched) so we can restore it.
759         // We can restore m->curg->sched.sp easily, because calling
760         // runtime.cgocallbackg leaves SP unchanged upon return.
761         // To save m->curg->sched.pc, we push it onto the curg stack and
762         // open a frame the same size as cgocallback's g0 frame.
763         // Once we switch to the curg stack, the pushed PC will appear
764         // to be the return PC of cgocallback, so that the traceback
765         // will seamlessly trace back into the earlier calls.
766         MOVL    m_curg(BP), SI
767         MOVL    SI, g(CX)
768         MOVL    (g_sched+gobuf_sp)(SI), DI // prepare stack as DI
769         MOVL    (g_sched+gobuf_pc)(SI), BP
770         MOVL    BP, -4(DI)  // "push" return PC on the g stack
771         // Gather our arguments into registers.
772         MOVL    fn+0(FP), AX
773         MOVL    frame+4(FP), BX
774         MOVL    ctxt+8(FP), CX
775         LEAL    -(4+12)(DI), SP  // Must match declared frame size
776         MOVL    AX, 0(SP)
777         MOVL    BX, 4(SP)
778         MOVL    CX, 8(SP)
779         CALL    runtime·cgocallbackg(SB)
780
781         // Restore g->sched (== m->curg->sched) from saved values.
782         get_tls(CX)
783         MOVL    g(CX), SI
784         MOVL    12(SP), BP  // Must match declared frame size
785         MOVL    BP, (g_sched+gobuf_pc)(SI)
786         LEAL    (12+4)(SP), DI  // Must match declared frame size
787         MOVL    DI, (g_sched+gobuf_sp)(SI)
788
789         // Switch back to m->g0's stack and restore m->g0->sched.sp.
790         // (Unlike m->curg, the g0 goroutine never uses sched.pc,
791         // so we do not have to restore it.)
792         MOVL    g(CX), BP
793         MOVL    g_m(BP), BP
794         MOVL    m_g0(BP), SI
795         MOVL    SI, g(CX)
796         MOVL    (g_sched+gobuf_sp)(SI), SP
797         MOVL    0(SP), AX
798         MOVL    AX, (g_sched+gobuf_sp)(SI)
799
800         // If the m on entry was nil, we called needm above to borrow an m,
801         // 1. for the duration of the call on non-pthread platforms,
802         // 2. or the duration of the C thread alive on pthread platforms.
803         // If the m on entry wasn't nil,
804         // 1. the thread might be a Go thread,
805         // 2. or it's wasn't the first call from a C thread on pthread platforms,
806         //    since the we skip dropm to resue the m in the first call.
807         MOVL    savedm-4(SP), DX
808         CMPL    DX, $0
809         JNE     droppedm
810
811         // Skip dropm to reuse it in the next call, when a pthread key has been created.
812         MOVL    _cgo_pthread_key_created(SB), DX
813         // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
814         CMPL    DX, $0
815         JEQ     dropm
816         CMPL    (DX), $0
817         JNE     droppedm
818
819 dropm:
820         MOVL    $runtime·dropm(SB), AX
821         CALL    AX
822 droppedm:
823
824         // Done!
825         RET
826
827 // void setg(G*); set g. for use by needm.
828 TEXT runtime·setg(SB), NOSPLIT, $0-4
829         MOVL    gg+0(FP), BX
830 #ifdef GOOS_windows
831         MOVL    runtime·tls_g(SB), CX
832         CMPL    BX, $0
833         JNE     settls
834         MOVL    $0, 0(CX)(FS)
835         RET
836 settls:
837         MOVL    g_m(BX), AX
838         LEAL    m_tls(AX), AX
839         MOVL    AX, 0(CX)(FS)
840 #endif
841         get_tls(CX)
842         MOVL    BX, g(CX)
843         RET
844
845 // void setg_gcc(G*); set g. for use by gcc
846 TEXT setg_gcc<>(SB), NOSPLIT, $0
847         get_tls(AX)
848         MOVL    gg+0(FP), DX
849         MOVL    DX, g(AX)
850         RET
851
852 TEXT runtime·abort(SB),NOSPLIT,$0-0
853         INT     $3
854 loop:
855         JMP     loop
856
857 // check that SP is in range [g->stack.lo, g->stack.hi)
858 TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
859         get_tls(CX)
860         MOVL    g(CX), AX
861         CMPL    (g_stack+stack_hi)(AX), SP
862         JHI     2(PC)
863         CALL    runtime·abort(SB)
864         CMPL    SP, (g_stack+stack_lo)(AX)
865         JHI     2(PC)
866         CALL    runtime·abort(SB)
867         RET
868
869 // func cputicks() int64
870 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
871         // LFENCE/MFENCE instruction support is dependent on SSE2.
872         // When no SSE2 support is present do not enforce any serialization
873         // since using CPUID to serialize the instruction stream is
874         // very costly.
875 #ifdef GO386_softfloat
876         JMP     rdtsc  // no fence instructions available
877 #endif
878         CMPB    internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1
879         JNE     fences
880         // Instruction stream serializing RDTSCP is supported.
881         // RDTSCP is supported by Intel Nehalem (2008) and
882         // AMD K8 Rev. F (2006) and newer.
883         RDTSCP
884 done:
885         MOVL    AX, ret_lo+0(FP)
886         MOVL    DX, ret_hi+4(FP)
887         RET
888 fences:
889         // MFENCE is instruction stream serializing and flushes the
890         // store buffers on AMD. The serialization semantics of LFENCE on AMD
891         // are dependent on MSR C001_1029 and CPU generation.
892         // LFENCE on Intel does wait for all previous instructions to have executed.
893         // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all
894         // previous instructions executed and all previous loads and stores to globally visible.
895         // Using MFENCE;LFENCE here aligns the serializing properties without
896         // runtime detection of CPU manufacturer.
897         MFENCE
898         LFENCE
899 rdtsc:
900         RDTSC
901         JMP done
902
903 TEXT ldt0setup<>(SB),NOSPLIT,$16-0
904 #ifdef GOOS_windows
905         CALL    runtime·wintls(SB)
906 #endif
907         // set up ldt 7 to point at m0.tls
908         // ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
909         // the entry number is just a hint.  setldt will set up GS with what it used.
910         MOVL    $7, 0(SP)
911         LEAL    runtime·m0+m_tls(SB), AX
912         MOVL    AX, 4(SP)
913         MOVL    $32, 8(SP)      // sizeof(tls array)
914         CALL    runtime·setldt(SB)
915         RET
916
917 TEXT runtime·emptyfunc(SB),0,$0-0
918         RET
919
920 // hash function using AES hardware instructions
921 TEXT runtime·memhash(SB),NOSPLIT,$0-16
922         CMPB    runtime·useAeshash(SB), $0
923         JEQ     noaes
924         MOVL    p+0(FP), AX     // ptr to data
925         MOVL    s+8(FP), BX     // size
926         LEAL    ret+12(FP), DX
927         JMP     aeshashbody<>(SB)
928 noaes:
929         JMP     runtime·memhashFallback(SB)
930
931 TEXT runtime·strhash(SB),NOSPLIT,$0-12
932         CMPB    runtime·useAeshash(SB), $0
933         JEQ     noaes
934         MOVL    p+0(FP), AX     // ptr to string object
935         MOVL    4(AX), BX       // length of string
936         MOVL    (AX), AX        // string data
937         LEAL    ret+8(FP), DX
938         JMP     aeshashbody<>(SB)
939 noaes:
940         JMP     runtime·strhashFallback(SB)
941
942 // AX: data
943 // BX: length
944 // DX: address to put return value
945 TEXT aeshashbody<>(SB),NOSPLIT,$0-0
946         MOVL    h+4(FP), X0                 // 32 bits of per-table hash seed
947         PINSRW  $4, BX, X0                  // 16 bits of length
948         PSHUFHW $0, X0, X0                  // replace size with its low 2 bytes repeated 4 times
949         MOVO    X0, X1                      // save unscrambled seed
950         PXOR    runtime·aeskeysched(SB), X0 // xor in per-process seed
951         AESENC  X0, X0                      // scramble seed
952
953         CMPL    BX, $16
954         JB      aes0to15
955         JE      aes16
956         CMPL    BX, $32
957         JBE     aes17to32
958         CMPL    BX, $64
959         JBE     aes33to64
960         JMP     aes65plus
961
962 aes0to15:
963         TESTL   BX, BX
964         JE      aes0
965
966         ADDL    $16, AX
967         TESTW   $0xff0, AX
968         JE      endofpage
969
970         // 16 bytes loaded at this address won't cross
971         // a page boundary, so we can load it directly.
972         MOVOU   -16(AX), X1
973         ADDL    BX, BX
974         PAND    masks<>(SB)(BX*8), X1
975
976 final1:
977         PXOR    X0, X1  // xor data with seed
978         AESENC  X1, X1  // scramble combo 3 times
979         AESENC  X1, X1
980         AESENC  X1, X1
981         MOVL    X1, (DX)
982         RET
983
984 endofpage:
985         // address ends in 1111xxxx. Might be up against
986         // a page boundary, so load ending at last byte.
987         // Then shift bytes down using pshufb.
988         MOVOU   -32(AX)(BX*1), X1
989         ADDL    BX, BX
990         PSHUFB  shifts<>(SB)(BX*8), X1
991         JMP     final1
992
993 aes0:
994         // Return scrambled input seed
995         AESENC  X0, X0
996         MOVL    X0, (DX)
997         RET
998
999 aes16:
1000         MOVOU   (AX), X1
1001         JMP     final1
1002
1003 aes17to32:
1004         // make second starting seed
1005         PXOR    runtime·aeskeysched+16(SB), X1
1006         AESENC  X1, X1
1007
1008         // load data to be hashed
1009         MOVOU   (AX), X2
1010         MOVOU   -16(AX)(BX*1), X3
1011
1012         // xor with seed
1013         PXOR    X0, X2
1014         PXOR    X1, X3
1015
1016         // scramble 3 times
1017         AESENC  X2, X2
1018         AESENC  X3, X3
1019         AESENC  X2, X2
1020         AESENC  X3, X3
1021         AESENC  X2, X2
1022         AESENC  X3, X3
1023
1024         // combine results
1025         PXOR    X3, X2
1026         MOVL    X2, (DX)
1027         RET
1028
1029 aes33to64:
1030         // make 3 more starting seeds
1031         MOVO    X1, X2
1032         MOVO    X1, X3
1033         PXOR    runtime·aeskeysched+16(SB), X1
1034         PXOR    runtime·aeskeysched+32(SB), X2
1035         PXOR    runtime·aeskeysched+48(SB), X3
1036         AESENC  X1, X1
1037         AESENC  X2, X2
1038         AESENC  X3, X3
1039
1040         MOVOU   (AX), X4
1041         MOVOU   16(AX), X5
1042         MOVOU   -32(AX)(BX*1), X6
1043         MOVOU   -16(AX)(BX*1), X7
1044
1045         PXOR    X0, X4
1046         PXOR    X1, X5
1047         PXOR    X2, X6
1048         PXOR    X3, X7
1049
1050         AESENC  X4, X4
1051         AESENC  X5, X5
1052         AESENC  X6, X6
1053         AESENC  X7, X7
1054
1055         AESENC  X4, X4
1056         AESENC  X5, X5
1057         AESENC  X6, X6
1058         AESENC  X7, X7
1059
1060         AESENC  X4, X4
1061         AESENC  X5, X5
1062         AESENC  X6, X6
1063         AESENC  X7, X7
1064
1065         PXOR    X6, X4
1066         PXOR    X7, X5
1067         PXOR    X5, X4
1068         MOVL    X4, (DX)
1069         RET
1070
1071 aes65plus:
1072         // make 3 more starting seeds
1073         MOVO    X1, X2
1074         MOVO    X1, X3
1075         PXOR    runtime·aeskeysched+16(SB), X1
1076         PXOR    runtime·aeskeysched+32(SB), X2
1077         PXOR    runtime·aeskeysched+48(SB), X3
1078         AESENC  X1, X1
1079         AESENC  X2, X2
1080         AESENC  X3, X3
1081
1082         // start with last (possibly overlapping) block
1083         MOVOU   -64(AX)(BX*1), X4
1084         MOVOU   -48(AX)(BX*1), X5
1085         MOVOU   -32(AX)(BX*1), X6
1086         MOVOU   -16(AX)(BX*1), X7
1087
1088         // scramble state once
1089         AESENC  X0, X4
1090         AESENC  X1, X5
1091         AESENC  X2, X6
1092         AESENC  X3, X7
1093
1094         // compute number of remaining 64-byte blocks
1095         DECL    BX
1096         SHRL    $6, BX
1097
1098 aesloop:
1099         // scramble state, xor in a block
1100         MOVOU   (AX), X0
1101         MOVOU   16(AX), X1
1102         MOVOU   32(AX), X2
1103         MOVOU   48(AX), X3
1104         AESENC  X0, X4
1105         AESENC  X1, X5
1106         AESENC  X2, X6
1107         AESENC  X3, X7
1108
1109         // scramble state
1110         AESENC  X4, X4
1111         AESENC  X5, X5
1112         AESENC  X6, X6
1113         AESENC  X7, X7
1114
1115         ADDL    $64, AX
1116         DECL    BX
1117         JNE     aesloop
1118
1119         // 3 more scrambles to finish
1120         AESENC  X4, X4
1121         AESENC  X5, X5
1122         AESENC  X6, X6
1123         AESENC  X7, X7
1124
1125         AESENC  X4, X4
1126         AESENC  X5, X5
1127         AESENC  X6, X6
1128         AESENC  X7, X7
1129
1130         AESENC  X4, X4
1131         AESENC  X5, X5
1132         AESENC  X6, X6
1133         AESENC  X7, X7
1134
1135         PXOR    X6, X4
1136         PXOR    X7, X5
1137         PXOR    X5, X4
1138         MOVL    X4, (DX)
1139         RET
1140
1141 TEXT runtime·memhash32(SB),NOSPLIT,$0-12
1142         CMPB    runtime·useAeshash(SB), $0
1143         JEQ     noaes
1144         MOVL    p+0(FP), AX     // ptr to data
1145         MOVL    h+4(FP), X0     // seed
1146         PINSRD  $1, (AX), X0    // data
1147         AESENC  runtime·aeskeysched+0(SB), X0
1148         AESENC  runtime·aeskeysched+16(SB), X0
1149         AESENC  runtime·aeskeysched+32(SB), X0
1150         MOVL    X0, ret+8(FP)
1151         RET
1152 noaes:
1153         JMP     runtime·memhash32Fallback(SB)
1154
1155 TEXT runtime·memhash64(SB),NOSPLIT,$0-12
1156         CMPB    runtime·useAeshash(SB), $0
1157         JEQ     noaes
1158         MOVL    p+0(FP), AX     // ptr to data
1159         MOVQ    (AX), X0        // data
1160         PINSRD  $2, h+4(FP), X0 // seed
1161         AESENC  runtime·aeskeysched+0(SB), X0
1162         AESENC  runtime·aeskeysched+16(SB), X0
1163         AESENC  runtime·aeskeysched+32(SB), X0
1164         MOVL    X0, ret+8(FP)
1165         RET
1166 noaes:
1167         JMP     runtime·memhash64Fallback(SB)
1168
1169 // simple mask to get rid of data in the high part of the register.
1170 DATA masks<>+0x00(SB)/4, $0x00000000
1171 DATA masks<>+0x04(SB)/4, $0x00000000
1172 DATA masks<>+0x08(SB)/4, $0x00000000
1173 DATA masks<>+0x0c(SB)/4, $0x00000000
1174
1175 DATA masks<>+0x10(SB)/4, $0x000000ff
1176 DATA masks<>+0x14(SB)/4, $0x00000000
1177 DATA masks<>+0x18(SB)/4, $0x00000000
1178 DATA masks<>+0x1c(SB)/4, $0x00000000
1179
1180 DATA masks<>+0x20(SB)/4, $0x0000ffff
1181 DATA masks<>+0x24(SB)/4, $0x00000000
1182 DATA masks<>+0x28(SB)/4, $0x00000000
1183 DATA masks<>+0x2c(SB)/4, $0x00000000
1184
1185 DATA masks<>+0x30(SB)/4, $0x00ffffff
1186 DATA masks<>+0x34(SB)/4, $0x00000000
1187 DATA masks<>+0x38(SB)/4, $0x00000000
1188 DATA masks<>+0x3c(SB)/4, $0x00000000
1189
1190 DATA masks<>+0x40(SB)/4, $0xffffffff
1191 DATA masks<>+0x44(SB)/4, $0x00000000
1192 DATA masks<>+0x48(SB)/4, $0x00000000
1193 DATA masks<>+0x4c(SB)/4, $0x00000000
1194
1195 DATA masks<>+0x50(SB)/4, $0xffffffff
1196 DATA masks<>+0x54(SB)/4, $0x000000ff
1197 DATA masks<>+0x58(SB)/4, $0x00000000
1198 DATA masks<>+0x5c(SB)/4, $0x00000000
1199
1200 DATA masks<>+0x60(SB)/4, $0xffffffff
1201 DATA masks<>+0x64(SB)/4, $0x0000ffff
1202 DATA masks<>+0x68(SB)/4, $0x00000000
1203 DATA masks<>+0x6c(SB)/4, $0x00000000
1204
1205 DATA masks<>+0x70(SB)/4, $0xffffffff
1206 DATA masks<>+0x74(SB)/4, $0x00ffffff
1207 DATA masks<>+0x78(SB)/4, $0x00000000
1208 DATA masks<>+0x7c(SB)/4, $0x00000000
1209
1210 DATA masks<>+0x80(SB)/4, $0xffffffff
1211 DATA masks<>+0x84(SB)/4, $0xffffffff
1212 DATA masks<>+0x88(SB)/4, $0x00000000
1213 DATA masks<>+0x8c(SB)/4, $0x00000000
1214
1215 DATA masks<>+0x90(SB)/4, $0xffffffff
1216 DATA masks<>+0x94(SB)/4, $0xffffffff
1217 DATA masks<>+0x98(SB)/4, $0x000000ff
1218 DATA masks<>+0x9c(SB)/4, $0x00000000
1219
1220 DATA masks<>+0xa0(SB)/4, $0xffffffff
1221 DATA masks<>+0xa4(SB)/4, $0xffffffff
1222 DATA masks<>+0xa8(SB)/4, $0x0000ffff
1223 DATA masks<>+0xac(SB)/4, $0x00000000
1224
1225 DATA masks<>+0xb0(SB)/4, $0xffffffff
1226 DATA masks<>+0xb4(SB)/4, $0xffffffff
1227 DATA masks<>+0xb8(SB)/4, $0x00ffffff
1228 DATA masks<>+0xbc(SB)/4, $0x00000000
1229
1230 DATA masks<>+0xc0(SB)/4, $0xffffffff
1231 DATA masks<>+0xc4(SB)/4, $0xffffffff
1232 DATA masks<>+0xc8(SB)/4, $0xffffffff
1233 DATA masks<>+0xcc(SB)/4, $0x00000000
1234
1235 DATA masks<>+0xd0(SB)/4, $0xffffffff
1236 DATA masks<>+0xd4(SB)/4, $0xffffffff
1237 DATA masks<>+0xd8(SB)/4, $0xffffffff
1238 DATA masks<>+0xdc(SB)/4, $0x000000ff
1239
1240 DATA masks<>+0xe0(SB)/4, $0xffffffff
1241 DATA masks<>+0xe4(SB)/4, $0xffffffff
1242 DATA masks<>+0xe8(SB)/4, $0xffffffff
1243 DATA masks<>+0xec(SB)/4, $0x0000ffff
1244
1245 DATA masks<>+0xf0(SB)/4, $0xffffffff
1246 DATA masks<>+0xf4(SB)/4, $0xffffffff
1247 DATA masks<>+0xf8(SB)/4, $0xffffffff
1248 DATA masks<>+0xfc(SB)/4, $0x00ffffff
1249
1250 GLOBL masks<>(SB),RODATA,$256
1251
1252 // these are arguments to pshufb. They move data down from
1253 // the high bytes of the register to the low bytes of the register.
1254 // index is how many bytes to move.
1255 DATA shifts<>+0x00(SB)/4, $0x00000000
1256 DATA shifts<>+0x04(SB)/4, $0x00000000
1257 DATA shifts<>+0x08(SB)/4, $0x00000000
1258 DATA shifts<>+0x0c(SB)/4, $0x00000000
1259
1260 DATA shifts<>+0x10(SB)/4, $0xffffff0f
1261 DATA shifts<>+0x14(SB)/4, $0xffffffff
1262 DATA shifts<>+0x18(SB)/4, $0xffffffff
1263 DATA shifts<>+0x1c(SB)/4, $0xffffffff
1264
1265 DATA shifts<>+0x20(SB)/4, $0xffff0f0e
1266 DATA shifts<>+0x24(SB)/4, $0xffffffff
1267 DATA shifts<>+0x28(SB)/4, $0xffffffff
1268 DATA shifts<>+0x2c(SB)/4, $0xffffffff
1269
1270 DATA shifts<>+0x30(SB)/4, $0xff0f0e0d
1271 DATA shifts<>+0x34(SB)/4, $0xffffffff
1272 DATA shifts<>+0x38(SB)/4, $0xffffffff
1273 DATA shifts<>+0x3c(SB)/4, $0xffffffff
1274
1275 DATA shifts<>+0x40(SB)/4, $0x0f0e0d0c
1276 DATA shifts<>+0x44(SB)/4, $0xffffffff
1277 DATA shifts<>+0x48(SB)/4, $0xffffffff
1278 DATA shifts<>+0x4c(SB)/4, $0xffffffff
1279
1280 DATA shifts<>+0x50(SB)/4, $0x0e0d0c0b
1281 DATA shifts<>+0x54(SB)/4, $0xffffff0f
1282 DATA shifts<>+0x58(SB)/4, $0xffffffff
1283 DATA shifts<>+0x5c(SB)/4, $0xffffffff
1284
1285 DATA shifts<>+0x60(SB)/4, $0x0d0c0b0a
1286 DATA shifts<>+0x64(SB)/4, $0xffff0f0e
1287 DATA shifts<>+0x68(SB)/4, $0xffffffff
1288 DATA shifts<>+0x6c(SB)/4, $0xffffffff
1289
1290 DATA shifts<>+0x70(SB)/4, $0x0c0b0a09
1291 DATA shifts<>+0x74(SB)/4, $0xff0f0e0d
1292 DATA shifts<>+0x78(SB)/4, $0xffffffff
1293 DATA shifts<>+0x7c(SB)/4, $0xffffffff
1294
1295 DATA shifts<>+0x80(SB)/4, $0x0b0a0908
1296 DATA shifts<>+0x84(SB)/4, $0x0f0e0d0c
1297 DATA shifts<>+0x88(SB)/4, $0xffffffff
1298 DATA shifts<>+0x8c(SB)/4, $0xffffffff
1299
1300 DATA shifts<>+0x90(SB)/4, $0x0a090807
1301 DATA shifts<>+0x94(SB)/4, $0x0e0d0c0b
1302 DATA shifts<>+0x98(SB)/4, $0xffffff0f
1303 DATA shifts<>+0x9c(SB)/4, $0xffffffff
1304
1305 DATA shifts<>+0xa0(SB)/4, $0x09080706
1306 DATA shifts<>+0xa4(SB)/4, $0x0d0c0b0a
1307 DATA shifts<>+0xa8(SB)/4, $0xffff0f0e
1308 DATA shifts<>+0xac(SB)/4, $0xffffffff
1309
1310 DATA shifts<>+0xb0(SB)/4, $0x08070605
1311 DATA shifts<>+0xb4(SB)/4, $0x0c0b0a09
1312 DATA shifts<>+0xb8(SB)/4, $0xff0f0e0d
1313 DATA shifts<>+0xbc(SB)/4, $0xffffffff
1314
1315 DATA shifts<>+0xc0(SB)/4, $0x07060504
1316 DATA shifts<>+0xc4(SB)/4, $0x0b0a0908
1317 DATA shifts<>+0xc8(SB)/4, $0x0f0e0d0c
1318 DATA shifts<>+0xcc(SB)/4, $0xffffffff
1319
1320 DATA shifts<>+0xd0(SB)/4, $0x06050403
1321 DATA shifts<>+0xd4(SB)/4, $0x0a090807
1322 DATA shifts<>+0xd8(SB)/4, $0x0e0d0c0b
1323 DATA shifts<>+0xdc(SB)/4, $0xffffff0f
1324
1325 DATA shifts<>+0xe0(SB)/4, $0x05040302
1326 DATA shifts<>+0xe4(SB)/4, $0x09080706
1327 DATA shifts<>+0xe8(SB)/4, $0x0d0c0b0a
1328 DATA shifts<>+0xec(SB)/4, $0xffff0f0e
1329
1330 DATA shifts<>+0xf0(SB)/4, $0x04030201
1331 DATA shifts<>+0xf4(SB)/4, $0x08070605
1332 DATA shifts<>+0xf8(SB)/4, $0x0c0b0a09
1333 DATA shifts<>+0xfc(SB)/4, $0xff0f0e0d
1334
1335 GLOBL shifts<>(SB),RODATA,$256
1336
1337 TEXT ·checkASM(SB),NOSPLIT,$0-1
1338         // check that masks<>(SB) and shifts<>(SB) are aligned to 16-byte
1339         MOVL    $masks<>(SB), AX
1340         MOVL    $shifts<>(SB), BX
1341         ORL     BX, AX
1342         TESTL   $15, AX
1343         SETEQ   ret+0(FP)
1344         RET
1345
1346 TEXT runtime·return0(SB), NOSPLIT, $0
1347         MOVL    $0, AX
1348         RET
1349
1350 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
1351 // Must obey the gcc calling convention.
1352 TEXT _cgo_topofstack(SB),NOSPLIT,$0
1353         get_tls(CX)
1354         MOVL    g(CX), AX
1355         MOVL    g_m(AX), AX
1356         MOVL    m_curg(AX), AX
1357         MOVL    (g_stack+stack_hi)(AX), AX
1358         RET
1359
1360 // The top-most function running on a goroutine
1361 // returns to goexit+PCQuantum.
1362 TEXT runtime·goexit(SB),NOSPLIT|TOPFRAME,$0-0
1363         BYTE    $0x90   // NOP
1364         CALL    runtime·goexit1(SB)    // does not return
1365         // traceback from goexit1 must hit code range of goexit
1366         BYTE    $0x90   // NOP
1367
1368 // Add a module's moduledata to the linked list of moduledata objects. This
1369 // is called from .init_array by a function generated in the linker and so
1370 // follows the platform ABI wrt register preservation -- it only touches AX,
1371 // CX (implicitly) and DX, but it does not follow the ABI wrt arguments:
1372 // instead the pointer to the moduledata is passed in AX.
1373 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
1374         MOVL    runtime·lastmoduledatap(SB), DX
1375         MOVL    AX, moduledata_next(DX)
1376         MOVL    AX, runtime·lastmoduledatap(SB)
1377         RET
1378
1379 TEXT runtime·uint32tofloat64(SB),NOSPLIT,$8-12
1380         MOVL    a+0(FP), AX
1381         MOVL    AX, 0(SP)
1382         MOVL    $0, 4(SP)
1383         FMOVV   0(SP), F0
1384         FMOVDP  F0, ret+4(FP)
1385         RET
1386
1387 TEXT runtime·float64touint32(SB),NOSPLIT,$12-12
1388         FMOVD   a+0(FP), F0
1389         FSTCW   0(SP)
1390         FLDCW   runtime·controlWord64trunc(SB)
1391         FMOVVP  F0, 4(SP)
1392         FLDCW   0(SP)
1393         MOVL    4(SP), AX
1394         MOVL    AX, ret+8(FP)
1395         RET
1396
1397 // gcWriteBarrier informs the GC about heap pointer writes.
1398 //
1399 // gcWriteBarrier returns space in a write barrier buffer which
1400 // should be filled in by the caller.
1401 // gcWriteBarrier does NOT follow the Go ABI. It accepts the
1402 // number of bytes of buffer needed in DI, and returns a pointer
1403 // to the buffer space in DI.
1404 // It clobbers FLAGS. It does not clobber any general-purpose registers,
1405 // but may clobber others (e.g., SSE registers).
1406 // Typical use would be, when doing *(CX+88) = AX
1407 //     CMPL    $0, runtime.writeBarrier(SB)
1408 //     JEQ     dowrite
1409 //     CALL    runtime.gcBatchBarrier2(SB)
1410 //     MOVL    AX, (DI)
1411 //     MOVL    88(CX), DX
1412 //     MOVL    DX, 4(DI)
1413 // dowrite:
1414 //     MOVL    AX, 88(CX)
1415 TEXT gcWriteBarrier<>(SB),NOSPLIT,$28
1416         // Save the registers clobbered by the fast path. This is slightly
1417         // faster than having the caller spill these.
1418         MOVL    CX, 20(SP)
1419         MOVL    BX, 24(SP)
1420 retry:
1421         // TODO: Consider passing g.m.p in as an argument so they can be shared
1422         // across a sequence of write barriers.
1423         get_tls(BX)
1424         MOVL    g(BX), BX
1425         MOVL    g_m(BX), BX
1426         MOVL    m_p(BX), BX
1427         // Get current buffer write position.
1428         MOVL    (p_wbBuf+wbBuf_next)(BX), CX    // original next position
1429         ADDL    DI, CX                          // new next position
1430         // Is the buffer full?
1431         CMPL    CX, (p_wbBuf+wbBuf_end)(BX)
1432         JA      flush
1433         // Commit to the larger buffer.
1434         MOVL    CX, (p_wbBuf+wbBuf_next)(BX)
1435         // Make return value (the original next position)
1436         SUBL    DI, CX
1437         MOVL    CX, DI
1438         // Restore registers.
1439         MOVL    20(SP), CX
1440         MOVL    24(SP), BX
1441         RET
1442
1443 flush:
1444         // Save all general purpose registers since these could be
1445         // clobbered by wbBufFlush and were not saved by the caller.
1446         MOVL    DI, 0(SP)
1447         MOVL    AX, 4(SP)
1448         // BX already saved
1449         // CX already saved
1450         MOVL    DX, 8(SP)
1451         MOVL    BP, 12(SP)
1452         MOVL    SI, 16(SP)
1453         // DI already saved
1454
1455         CALL    runtime·wbBufFlush(SB)
1456
1457         MOVL    0(SP), DI
1458         MOVL    4(SP), AX
1459         MOVL    8(SP), DX
1460         MOVL    12(SP), BP
1461         MOVL    16(SP), SI
1462         JMP     retry
1463
1464 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
1465         MOVL    $4, DI
1466         JMP     gcWriteBarrier<>(SB)
1467 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
1468         MOVL    $8, DI
1469         JMP     gcWriteBarrier<>(SB)
1470 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
1471         MOVL    $12, DI
1472         JMP     gcWriteBarrier<>(SB)
1473 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
1474         MOVL    $16, DI
1475         JMP     gcWriteBarrier<>(SB)
1476 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
1477         MOVL    $20, DI
1478         JMP     gcWriteBarrier<>(SB)
1479 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
1480         MOVL    $24, DI
1481         JMP     gcWriteBarrier<>(SB)
1482 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
1483         MOVL    $28, DI
1484         JMP     gcWriteBarrier<>(SB)
1485 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
1486         MOVL    $32, DI
1487         JMP     gcWriteBarrier<>(SB)
1488
1489 // Note: these functions use a special calling convention to save generated code space.
1490 // Arguments are passed in registers, but the space for those arguments are allocated
1491 // in the caller's stack frame. These stubs write the args into that stack space and
1492 // then tail call to the corresponding runtime handler.
1493 // The tail call makes these stubs disappear in backtraces.
1494 TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
1495         MOVL    AX, x+0(FP)
1496         MOVL    CX, y+4(FP)
1497         JMP     runtime·goPanicIndex(SB)
1498 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
1499         MOVL    AX, x+0(FP)
1500         MOVL    CX, y+4(FP)
1501         JMP     runtime·goPanicIndexU(SB)
1502 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
1503         MOVL    CX, x+0(FP)
1504         MOVL    DX, y+4(FP)
1505         JMP     runtime·goPanicSliceAlen(SB)
1506 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
1507         MOVL    CX, x+0(FP)
1508         MOVL    DX, y+4(FP)
1509         JMP     runtime·goPanicSliceAlenU(SB)
1510 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
1511         MOVL    CX, x+0(FP)
1512         MOVL    DX, y+4(FP)
1513         JMP     runtime·goPanicSliceAcap(SB)
1514 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
1515         MOVL    CX, x+0(FP)
1516         MOVL    DX, y+4(FP)
1517         JMP     runtime·goPanicSliceAcapU(SB)
1518 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
1519         MOVL    AX, x+0(FP)
1520         MOVL    CX, y+4(FP)
1521         JMP     runtime·goPanicSliceB(SB)
1522 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
1523         MOVL    AX, x+0(FP)
1524         MOVL    CX, y+4(FP)
1525         JMP     runtime·goPanicSliceBU(SB)
1526 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
1527         MOVL    DX, x+0(FP)
1528         MOVL    BX, y+4(FP)
1529         JMP     runtime·goPanicSlice3Alen(SB)
1530 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
1531         MOVL    DX, x+0(FP)
1532         MOVL    BX, y+4(FP)
1533         JMP     runtime·goPanicSlice3AlenU(SB)
1534 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
1535         MOVL    DX, x+0(FP)
1536         MOVL    BX, y+4(FP)
1537         JMP     runtime·goPanicSlice3Acap(SB)
1538 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
1539         MOVL    DX, x+0(FP)
1540         MOVL    BX, y+4(FP)
1541         JMP     runtime·goPanicSlice3AcapU(SB)
1542 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
1543         MOVL    CX, x+0(FP)
1544         MOVL    DX, y+4(FP)
1545         JMP     runtime·goPanicSlice3B(SB)
1546 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
1547         MOVL    CX, x+0(FP)
1548         MOVL    DX, y+4(FP)
1549         JMP     runtime·goPanicSlice3BU(SB)
1550 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
1551         MOVL    AX, x+0(FP)
1552         MOVL    CX, y+4(FP)
1553         JMP     runtime·goPanicSlice3C(SB)
1554 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
1555         MOVL    AX, x+0(FP)
1556         MOVL    CX, y+4(FP)
1557         JMP     runtime·goPanicSlice3CU(SB)
1558 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8
1559         MOVL    DX, x+0(FP)
1560         MOVL    BX, y+4(FP)
1561         JMP     runtime·goPanicSliceConvert(SB)
1562
1563 // Extended versions for 64-bit indexes.
1564 TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
1565         MOVL    SI, hi+0(FP)
1566         MOVL    AX, lo+4(FP)
1567         MOVL    CX, y+8(FP)
1568         JMP     runtime·goPanicExtendIndex(SB)
1569 TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
1570         MOVL    SI, hi+0(FP)
1571         MOVL    AX, lo+4(FP)
1572         MOVL    CX, y+8(FP)
1573         JMP     runtime·goPanicExtendIndexU(SB)
1574 TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
1575         MOVL    SI, hi+0(FP)
1576         MOVL    CX, lo+4(FP)
1577         MOVL    DX, y+8(FP)
1578         JMP     runtime·goPanicExtendSliceAlen(SB)
1579 TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
1580         MOVL    SI, hi+0(FP)
1581         MOVL    CX, lo+4(FP)
1582         MOVL    DX, y+8(FP)
1583         JMP     runtime·goPanicExtendSliceAlenU(SB)
1584 TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
1585         MOVL    SI, hi+0(FP)
1586         MOVL    CX, lo+4(FP)
1587         MOVL    DX, y+8(FP)
1588         JMP     runtime·goPanicExtendSliceAcap(SB)
1589 TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
1590         MOVL    SI, hi+0(FP)
1591         MOVL    CX, lo+4(FP)
1592         MOVL    DX, y+8(FP)
1593         JMP     runtime·goPanicExtendSliceAcapU(SB)
1594 TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
1595         MOVL    SI, hi+0(FP)
1596         MOVL    AX, lo+4(FP)
1597         MOVL    CX, y+8(FP)
1598         JMP     runtime·goPanicExtendSliceB(SB)
1599 TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
1600         MOVL    SI, hi+0(FP)
1601         MOVL    AX, lo+4(FP)
1602         MOVL    CX, y+8(FP)
1603         JMP     runtime·goPanicExtendSliceBU(SB)
1604 TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
1605         MOVL    SI, hi+0(FP)
1606         MOVL    DX, lo+4(FP)
1607         MOVL    BX, y+8(FP)
1608         JMP     runtime·goPanicExtendSlice3Alen(SB)
1609 TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
1610         MOVL    SI, hi+0(FP)
1611         MOVL    DX, lo+4(FP)
1612         MOVL    BX, y+8(FP)
1613         JMP     runtime·goPanicExtendSlice3AlenU(SB)
1614 TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
1615         MOVL    SI, hi+0(FP)
1616         MOVL    DX, lo+4(FP)
1617         MOVL    BX, y+8(FP)
1618         JMP     runtime·goPanicExtendSlice3Acap(SB)
1619 TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
1620         MOVL    SI, hi+0(FP)
1621         MOVL    DX, lo+4(FP)
1622         MOVL    BX, y+8(FP)
1623         JMP     runtime·goPanicExtendSlice3AcapU(SB)
1624 TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
1625         MOVL    SI, hi+0(FP)
1626         MOVL    CX, lo+4(FP)
1627         MOVL    DX, y+8(FP)
1628         JMP     runtime·goPanicExtendSlice3B(SB)
1629 TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
1630         MOVL    SI, hi+0(FP)
1631         MOVL    CX, lo+4(FP)
1632         MOVL    DX, y+8(FP)
1633         JMP     runtime·goPanicExtendSlice3BU(SB)
1634 TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
1635         MOVL    SI, hi+0(FP)
1636         MOVL    AX, lo+4(FP)
1637         MOVL    CX, y+8(FP)
1638         JMP     runtime·goPanicExtendSlice3C(SB)
1639 TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
1640         MOVL    SI, hi+0(FP)
1641         MOVL    AX, lo+4(FP)
1642         MOVL    CX, y+8(FP)
1643         JMP     runtime·goPanicExtendSlice3CU(SB)
1644
1645 #ifdef GOOS_android
1646 // Use the free TLS_SLOT_APP slot #2 on Android Q.
1647 // Earlier androids are set up in gcc_android.c.
1648 DATA runtime·tls_g+0(SB)/4, $8
1649 GLOBL runtime·tls_g+0(SB), NOPTR, $4
1650 #endif
1651 #ifdef GOOS_windows
1652 GLOBL runtime·tls_g+0(SB), NOPTR, $4
1653 #endif