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