Text file
src/runtime/asm_riscv64.s
1 // Copyright 2017 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 "funcdata.h"
7 #include "textflag.h"
8
9
10 // When building with -buildmode=c-shared, this symbol is called when the shared
11 // library is loaded.
12 TEXT _rt0_riscv64_lib(SB),NOSPLIT,$224
13 // Preserve callee-save registers, along with X1 (LR).
14 MOV X1, (8*3)(X2)
15 MOV X8, (8*4)(X2)
16 MOV X9, (8*5)(X2)
17 MOV X18, (8*6)(X2)
18 MOV X19, (8*7)(X2)
19 MOV X20, (8*8)(X2)
20 MOV X21, (8*9)(X2)
21 MOV X22, (8*10)(X2)
22 MOV X23, (8*11)(X2)
23 MOV X24, (8*12)(X2)
24 MOV X25, (8*13)(X2)
25 MOV X26, (8*14)(X2)
26 MOV g, (8*15)(X2)
27 MOVD F8, (8*16)(X2)
28 MOVD F9, (8*17)(X2)
29 MOVD F18, (8*18)(X2)
30 MOVD F19, (8*19)(X2)
31 MOVD F20, (8*20)(X2)
32 MOVD F21, (8*21)(X2)
33 MOVD F22, (8*22)(X2)
34 MOVD F23, (8*23)(X2)
35 MOVD F24, (8*24)(X2)
36 MOVD F25, (8*25)(X2)
37 MOVD F26, (8*26)(X2)
38 MOVD F27, (8*27)(X2)
39
40 // Initialize g as nil in case of using g later e.g. sigaction in cgo_sigaction.go
41 MOV X0, g
42
43 MOV A0, _rt0_riscv64_lib_argc<>(SB)
44 MOV A1, _rt0_riscv64_lib_argv<>(SB)
45
46 // Synchronous initialization.
47 MOV $runtime·libpreinit(SB), T0
48 JALR RA, T0
49
50 // Create a new thread to do the runtime initialization and return.
51 MOV _cgo_sys_thread_create(SB), T0
52 BEQZ T0, nocgo
53 MOV $_rt0_riscv64_lib_go(SB), A0
54 MOV $0, A1
55 JALR RA, T0
56 JMP restore
57
58 nocgo:
59 MOV $0x800000, A0 // stacksize = 8192KB
60 MOV $_rt0_riscv64_lib_go(SB), A1
61 MOV A0, 8(X2)
62 MOV A1, 16(X2)
63 MOV $runtime·newosproc0(SB), T0
64 JALR RA, T0
65
66 restore:
67 // Restore callee-save registers, along with X1 (LR).
68 MOV (8*3)(X2), X1
69 MOV (8*4)(X2), X8
70 MOV (8*5)(X2), X9
71 MOV (8*6)(X2), X18
72 MOV (8*7)(X2), X19
73 MOV (8*8)(X2), X20
74 MOV (8*9)(X2), X21
75 MOV (8*10)(X2), X22
76 MOV (8*11)(X2), X23
77 MOV (8*12)(X2), X24
78 MOV (8*13)(X2), X25
79 MOV (8*14)(X2), X26
80 MOV (8*15)(X2), g
81 MOVD (8*16)(X2), F8
82 MOVD (8*17)(X2), F9
83 MOVD (8*18)(X2), F18
84 MOVD (8*19)(X2), F19
85 MOVD (8*20)(X2), F20
86 MOVD (8*21)(X2), F21
87 MOVD (8*22)(X2), F22
88 MOVD (8*23)(X2), F23
89 MOVD (8*24)(X2), F24
90 MOVD (8*25)(X2), F25
91 MOVD (8*26)(X2), F26
92 MOVD (8*27)(X2), F27
93
94 RET
95
96 TEXT _rt0_riscv64_lib_go(SB),NOSPLIT,$0
97 MOV _rt0_riscv64_lib_argc<>(SB), A0
98 MOV _rt0_riscv64_lib_argv<>(SB), A1
99 MOV $runtime·rt0_go(SB), T0
100 JALR ZERO, T0
101
102 DATA _rt0_riscv64_lib_argc<>(SB)/8, $0
103 GLOBL _rt0_riscv64_lib_argc<>(SB),NOPTR, $8
104 DATA _rt0_riscv64_lib_argv<>(SB)/8, $0
105 GLOBL _rt0_riscv64_lib_argv<>(SB),NOPTR, $8
106
107 // func rt0_go()
108 TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
109 // X2 = stack; A0 = argc; A1 = argv
110 SUB $24, X2
111 MOV A0, 8(X2) // argc
112 MOV A1, 16(X2) // argv
113
114 // create istack out of the given (operating system) stack.
115 // _cgo_init may update stackguard.
116 MOV $runtime·g0(SB), g
117 MOV $(-64*1024), T0
118 ADD T0, X2, T1
119 MOV T1, g_stackguard0(g)
120 MOV T1, g_stackguard1(g)
121 MOV T1, (g_stack+stack_lo)(g)
122 MOV X2, (g_stack+stack_hi)(g)
123
124 // if there is a _cgo_init, call it using the gcc ABI.
125 MOV _cgo_init(SB), T0
126 BEQ T0, ZERO, nocgo
127
128 MOV ZERO, A3 // arg 3: not used
129 MOV ZERO, A2 // arg 2: not used
130 MOV $setg_gcc<>(SB), A1 // arg 1: setg
131 MOV g, A0 // arg 0: G
132 JALR RA, T0
133
134 nocgo:
135 // update stackguard after _cgo_init
136 MOV (g_stack+stack_lo)(g), T0
137 ADD $const_stackGuard, T0
138 MOV T0, g_stackguard0(g)
139 MOV T0, g_stackguard1(g)
140
141 // set the per-goroutine and per-mach "registers"
142 MOV $runtime·m0(SB), T0
143
144 // save m->g0 = g0
145 MOV g, m_g0(T0)
146 // save m0 to g0->m
147 MOV T0, g_m(g)
148
149 CALL runtime·check(SB)
150
151 // args are already prepared
152 CALL runtime·args(SB)
153 CALL runtime·osinit(SB)
154 CALL runtime·schedinit(SB)
155
156 // create a new goroutine to start program
157 MOV $runtime·mainPC(SB), T0 // entry
158 SUB $16, X2
159 MOV T0, 8(X2)
160 MOV ZERO, 0(X2)
161 CALL runtime·newproc(SB)
162 ADD $16, X2
163
164 // start this M
165 CALL runtime·mstart(SB)
166
167 WORD $0 // crash if reached
168 RET
169
170 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
171 CALL runtime·mstart0(SB)
172 RET // not reached
173
174 // void setg_gcc(G*); set g called from gcc with g in A0
175 TEXT setg_gcc<>(SB),NOSPLIT,$0-0
176 MOV A0, g
177 CALL runtime·save_g(SB)
178 RET
179
180 // func cputicks() int64
181 TEXT runtime·cputicks<ABIInternal>(SB),NOSPLIT,$0-0
182 // RDTIME to emulate cpu ticks
183 // RDCYCLE reads counter that is per HART(core) based
184 // according to the riscv manual, see issue 46737
185 RDTIME X10
186 RET
187
188 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
189 // of the G stack. We need to distinguish the routine that
190 // lives at the bottom of the G stack from the one that lives
191 // at the top of the system stack because the one at the top of
192 // the system stack terminates the stack walk (see topofstack()).
193 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
194 UNDEF
195 JALR RA, ZERO // make sure this function is not leaf
196 RET
197
198 // func systemstack(fn func())
199 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
200 MOV fn+0(FP), CTXT // CTXT = fn
201 MOV g_m(g), T0 // T0 = m
202
203 MOV m_gsignal(T0), T1 // T1 = gsignal
204 BEQ g, T1, noswitch
205
206 MOV m_g0(T0), T1 // T1 = g0
207 BEQ g, T1, noswitch
208
209 MOV m_curg(T0), T2
210 BEQ g, T2, switch
211
212 // Bad: g is not gsignal, not g0, not curg. What is it?
213 // Hide call from linker nosplit analysis.
214 MOV $runtime·badsystemstack(SB), T1
215 JALR RA, T1
216
217 switch:
218 // save our state in g->sched. Pretend to
219 // be systemstack_switch if the G stack is scanned.
220 CALL gosave_systemstack_switch<>(SB)
221
222 // switch to g0
223 MOV T1, g
224 CALL runtime·save_g(SB)
225 MOV (g_sched+gobuf_sp)(g), T0
226 MOV T0, X2
227
228 // call target function
229 MOV 0(CTXT), T1 // code pointer
230 JALR RA, T1
231
232 // switch back to g
233 MOV g_m(g), T0
234 MOV m_curg(T0), g
235 CALL runtime·save_g(SB)
236 MOV (g_sched+gobuf_sp)(g), X2
237 MOV ZERO, (g_sched+gobuf_sp)(g)
238 RET
239
240 noswitch:
241 // already on m stack, just call directly
242 // Using a tail call here cleans up tracebacks since we won't stop
243 // at an intermediate systemstack.
244 MOV 0(CTXT), T1 // code pointer
245 ADD $8, X2
246 JMP (T1)
247
248 // func switchToCrashStack0(fn func())
249 TEXT runtime·switchToCrashStack0<ABIInternal>(SB), NOSPLIT, $0-8
250 MOV X10, CTXT // context register
251 MOV g_m(g), X11 // curm
252
253 // set g to gcrash
254 MOV $runtime·gcrash(SB), g // g = &gcrash
255 CALL runtime·save_g(SB) // clobbers X31
256 MOV X11, g_m(g) // g.m = curm
257 MOV g, m_g0(X11) // curm.g0 = g
258
259 // switch to crashstack
260 MOV (g_stack+stack_hi)(g), X11
261 SUB $(4*8), X11
262 MOV X11, X2
263
264 // call target function
265 MOV 0(CTXT), X10
266 JALR X1, X10
267
268 // should never return
269 CALL runtime·abort(SB)
270 UNDEF
271
272 /*
273 * support for morestack
274 */
275
276 // Called during function prolog when more stack is needed.
277 // Called with return address (i.e. caller's PC) in X5 (aka T0),
278 // and the LR register contains the caller's LR.
279 //
280 // The traceback routines see morestack on a g0 as being
281 // the top of a stack (for example, morestack calling newstack
282 // calling the scheduler calling newm calling gc), so we must
283 // record an argument size. For that purpose, it has no arguments.
284
285 // func morestack()
286 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
287 // Called from f.
288 // Set g->sched to context in f.
289 MOV X2, (g_sched+gobuf_sp)(g)
290 MOV T0, (g_sched+gobuf_pc)(g)
291 MOV RA, (g_sched+gobuf_lr)(g)
292 MOV CTXT, (g_sched+gobuf_ctxt)(g)
293
294 // Cannot grow scheduler stack (m->g0).
295 MOV g_m(g), A0
296 MOV m_g0(A0), A1
297 BNE g, A1, 3(PC)
298 CALL runtime·badmorestackg0(SB)
299 CALL runtime·abort(SB)
300
301 // Cannot grow signal stack (m->gsignal).
302 MOV m_gsignal(A0), A1
303 BNE g, A1, 3(PC)
304 CALL runtime·badmorestackgsignal(SB)
305 CALL runtime·abort(SB)
306
307 // Called from f.
308 // Set m->morebuf to f's caller.
309 MOV RA, (m_morebuf+gobuf_pc)(A0) // f's caller's PC
310 MOV X2, (m_morebuf+gobuf_sp)(A0) // f's caller's SP
311 MOV g, (m_morebuf+gobuf_g)(A0)
312
313 // Call newstack on m->g0's stack.
314 MOV m_g0(A0), g
315 CALL runtime·save_g(SB)
316 MOV (g_sched+gobuf_sp)(g), X2
317 // Create a stack frame on g0 to call newstack.
318 MOV ZERO, -8(X2) // Zero saved LR in frame
319 SUB $8, X2
320 CALL runtime·newstack(SB)
321
322 // Not reached, but make sure the return PC from the call to newstack
323 // is still in this function, and not the beginning of the next.
324 UNDEF
325
326 // func morestack_noctxt()
327 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
328 // Force SPWRITE. This function doesn't actually write SP,
329 // but it is called with a special calling convention where
330 // the caller doesn't save LR on stack but passes it as a
331 // register, and the unwinder currently doesn't understand.
332 // Make it SPWRITE to stop unwinding. (See issue 54332)
333 MOV X2, X2
334
335 MOV ZERO, CTXT
336 JMP runtime·morestack(SB)
337
338 // AES hashing not implemented for riscv64
339 TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
340 JMP runtime·memhashFallback<ABIInternal>(SB)
341 TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
342 JMP runtime·strhashFallback<ABIInternal>(SB)
343 TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
344 JMP runtime·memhash32Fallback<ABIInternal>(SB)
345 TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
346 JMP runtime·memhash64Fallback<ABIInternal>(SB)
347
348 // restore state from Gobuf; longjmp
349
350 // func gogo(buf *gobuf)
351 TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
352 MOV buf+0(FP), T0
353 MOV gobuf_g(T0), T1
354 MOV 0(T1), ZERO // make sure g != nil
355 JMP gogo<>(SB)
356
357 TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
358 MOV T1, g
359 CALL runtime·save_g(SB)
360
361 MOV gobuf_sp(T0), X2
362 MOV gobuf_lr(T0), RA
363 MOV gobuf_ctxt(T0), CTXT
364 MOV ZERO, gobuf_sp(T0)
365 MOV ZERO, gobuf_lr(T0)
366 MOV ZERO, gobuf_ctxt(T0)
367 MOV gobuf_pc(T0), T0
368 JALR ZERO, T0
369
370 // func procyieldAsm(cycles uint32)
371 TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
372 RET
373
374 // Switch to m->g0's stack, call fn(g).
375 // Fn must never return. It should gogo(&g->sched)
376 // to keep running g.
377
378 // func mcall(fn func(*g))
379 TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8
380 MOV X10, CTXT
381
382 // Save caller state in g->sched
383 MOV X2, (g_sched+gobuf_sp)(g)
384 MOV RA, (g_sched+gobuf_pc)(g)
385 MOV ZERO, (g_sched+gobuf_lr)(g)
386
387 // Switch to m->g0 & its stack, call fn.
388 MOV g, X10
389 MOV g_m(g), T1
390 MOV m_g0(T1), g
391 CALL runtime·save_g(SB)
392 BNE g, X10, 2(PC)
393 JMP runtime·badmcall(SB)
394 MOV 0(CTXT), T1 // code pointer
395 MOV (g_sched+gobuf_sp)(g), X2 // sp = m->g0->sched.sp
396 // we don't need special macro for regabi since arg0(X10) = g
397 SUB $16, X2
398 MOV X10, 8(X2) // setup g
399 MOV ZERO, 0(X2) // clear return address
400 JALR RA, T1
401 JMP runtime·badmcall2(SB)
402
403 // Save state of caller into g->sched,
404 // but using fake PC from systemstack_switch.
405 // Must only be called from functions with no locals ($0)
406 // or else unwinding from systemstack_switch is incorrect.
407 // Smashes X31.
408 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
409 MOV $runtime·systemstack_switch(SB), X31
410 ADD $8, X31 // get past prologue
411 MOV X31, (g_sched+gobuf_pc)(g)
412 MOV X2, (g_sched+gobuf_sp)(g)
413 MOV ZERO, (g_sched+gobuf_lr)(g)
414 // Assert ctxt is zero. See func save.
415 MOV (g_sched+gobuf_ctxt)(g), X31
416 BEQ ZERO, X31, 2(PC)
417 CALL runtime·abort(SB)
418 RET
419
420 // func asmcgocall_no_g(fn, arg unsafe.Pointer)
421 // Call fn(arg) aligned appropriately for the gcc ABI.
422 // Called on a system stack, and there may be no g yet (during needm).
423 TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
424 MOV fn+0(FP), X5
425 MOV arg+8(FP), X10
426 JALR RA, (X5)
427 RET
428
429 // func asmcgocall(fn, arg unsafe.Pointer) int32
430 // Call fn(arg) on the scheduler stack,
431 // aligned appropriately for the gcc ABI.
432 // See cgocall.go for more details.
433 TEXT ·asmcgocall(SB),NOSPLIT,$0-20
434 MOV fn+0(FP), X5
435 MOV arg+8(FP), X10
436
437 MOV X2, X8 // save original stack pointer
438 MOV g, X9
439
440 // Figure out if we need to switch to m->g0 stack.
441 // We get called to create new OS threads too, and those
442 // come in on the m->g0 stack already. Or we might already
443 // be on the m->gsignal stack.
444 MOV g_m(g), X6
445 MOV m_gsignal(X6), X7
446 BEQ X7, g, g0
447 MOV m_g0(X6), X7
448 BEQ X7, g, g0
449
450 CALL gosave_systemstack_switch<>(SB)
451 MOV X7, g
452 CALL runtime·save_g(SB)
453 MOV (g_sched+gobuf_sp)(g), X2
454
455 // Now on a scheduling stack (a pthread-created stack).
456 g0:
457 // Save room for two of our pointers.
458 SUB $16, X2
459 MOV X9, 0(X2) // save old g on stack
460 MOV (g_stack+stack_hi)(X9), X9
461 SUB X8, X9, X8
462 MOV X8, 8(X2) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
463
464 JALR RA, (X5)
465
466 // Restore g, stack pointer. X10 is return value.
467 MOV 0(X2), g
468 CALL runtime·save_g(SB)
469 MOV (g_stack+stack_hi)(g), X5
470 MOV 8(X2), X6
471 SUB X6, X5, X6
472 MOV X6, X2
473
474 MOVW X10, ret+16(FP)
475 RET
476
477 // func asminit()
478 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
479 RET
480
481 // reflectcall: call a function with the given argument list
482 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
483 // we don't have variable-sized frames, so we use a small number
484 // of constant-sized-frame functions to encode a few bits of size in the pc.
485 // Caution: ugly multiline assembly macros in your future!
486
487 #define DISPATCH(NAME,MAXSIZE) \
488 MOV $MAXSIZE, T1 \
489 BLTU T1, T0, 3(PC) \
490 MOV $NAME(SB), T2; \
491 JALR ZERO, T2
492 // Note: can't just "BR NAME(SB)" - bad inlining results.
493
494 // func call(stackArgsType *rtype, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
495 TEXT reflect·call(SB), NOSPLIT, $0-0
496 JMP ·reflectcall(SB)
497
498 // func call(stackArgsType *_type, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
499 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
500 MOVWU frameSize+32(FP), T0
501 DISPATCH(runtime·call16, 16)
502 DISPATCH(runtime·call32, 32)
503 DISPATCH(runtime·call64, 64)
504 DISPATCH(runtime·call128, 128)
505 DISPATCH(runtime·call256, 256)
506 DISPATCH(runtime·call512, 512)
507 DISPATCH(runtime·call1024, 1024)
508 DISPATCH(runtime·call2048, 2048)
509 DISPATCH(runtime·call4096, 4096)
510 DISPATCH(runtime·call8192, 8192)
511 DISPATCH(runtime·call16384, 16384)
512 DISPATCH(runtime·call32768, 32768)
513 DISPATCH(runtime·call65536, 65536)
514 DISPATCH(runtime·call131072, 131072)
515 DISPATCH(runtime·call262144, 262144)
516 DISPATCH(runtime·call524288, 524288)
517 DISPATCH(runtime·call1048576, 1048576)
518 DISPATCH(runtime·call2097152, 2097152)
519 DISPATCH(runtime·call4194304, 4194304)
520 DISPATCH(runtime·call8388608, 8388608)
521 DISPATCH(runtime·call16777216, 16777216)
522 DISPATCH(runtime·call33554432, 33554432)
523 DISPATCH(runtime·call67108864, 67108864)
524 DISPATCH(runtime·call134217728, 134217728)
525 DISPATCH(runtime·call268435456, 268435456)
526 DISPATCH(runtime·call536870912, 536870912)
527 DISPATCH(runtime·call1073741824, 1073741824)
528 MOV $runtime·badreflectcall(SB), T2
529 JALR ZERO, T2
530
531 #define CALLFN(NAME,MAXSIZE) \
532 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
533 NO_LOCAL_POINTERS; \
534 /* copy arguments to stack */ \
535 MOV stackArgs+16(FP), A1; \
536 MOVWU stackArgsSize+24(FP), A2; \
537 MOV X2, A3; \
538 ADD $8, A3; \
539 ADD A3, A2; \
540 BEQ A3, A2, 6(PC); \
541 MOVBU (A1), A4; \
542 ADD $1, A1; \
543 MOVB A4, (A3); \
544 ADD $1, A3; \
545 JMP -5(PC); \
546 /* set up argument registers */ \
547 MOV regArgs+40(FP), X25; \
548 CALL ·unspillArgs(SB); \
549 /* call function */ \
550 MOV f+8(FP), CTXT; \
551 MOV (CTXT), X25; \
552 PCDATA $PCDATA_StackMapIndex, $0; \
553 JALR RA, X25; \
554 /* copy return values back */ \
555 MOV regArgs+40(FP), X25; \
556 CALL ·spillArgs(SB); \
557 MOV stackArgsType+0(FP), A5; \
558 MOV stackArgs+16(FP), A1; \
559 MOVWU stackArgsSize+24(FP), A2; \
560 MOVWU stackRetOffset+28(FP), A4; \
561 ADD $8, X2, A3; \
562 ADD A4, A3; \
563 ADD A4, A1; \
564 SUB A4, A2; \
565 CALL callRet<>(SB); \
566 RET
567
568 // callRet copies return values back at the end of call*. This is a
569 // separate function so it can allocate stack space for the arguments
570 // to reflectcallmove. It does not follow the Go ABI; it expects its
571 // arguments in registers.
572 TEXT callRet<>(SB), NOSPLIT, $40-0
573 NO_LOCAL_POINTERS
574 MOV A5, 8(X2)
575 MOV A1, 16(X2)
576 MOV A3, 24(X2)
577 MOV A2, 32(X2)
578 MOV X25, 40(X2)
579 CALL runtime·reflectcallmove(SB)
580 RET
581
582 CALLFN(·call16, 16)
583 CALLFN(·call32, 32)
584 CALLFN(·call64, 64)
585 CALLFN(·call128, 128)
586 CALLFN(·call256, 256)
587 CALLFN(·call512, 512)
588 CALLFN(·call1024, 1024)
589 CALLFN(·call2048, 2048)
590 CALLFN(·call4096, 4096)
591 CALLFN(·call8192, 8192)
592 CALLFN(·call16384, 16384)
593 CALLFN(·call32768, 32768)
594 CALLFN(·call65536, 65536)
595 CALLFN(·call131072, 131072)
596 CALLFN(·call262144, 262144)
597 CALLFN(·call524288, 524288)
598 CALLFN(·call1048576, 1048576)
599 CALLFN(·call2097152, 2097152)
600 CALLFN(·call4194304, 4194304)
601 CALLFN(·call8388608, 8388608)
602 CALLFN(·call16777216, 16777216)
603 CALLFN(·call33554432, 33554432)
604 CALLFN(·call67108864, 67108864)
605 CALLFN(·call134217728, 134217728)
606 CALLFN(·call268435456, 268435456)
607 CALLFN(·call536870912, 536870912)
608 CALLFN(·call1073741824, 1073741824)
609
610 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
611 // Must obey the gcc calling convention.
612 TEXT _cgo_topofstack(SB),NOSPLIT,$8
613 // g (X27) and REG_TMP (X31) might be clobbered by load_g.
614 // X27 is callee-save in the gcc calling convention, so save it.
615 MOV g, savedX27-8(SP)
616
617 CALL runtime·load_g(SB)
618 MOV g_m(g), X5
619 MOV m_curg(X5), X5
620 MOV (g_stack+stack_hi)(X5), X10 // return value in X10
621
622 MOV savedX27-8(SP), g
623 RET
624
625 // func goexit(neverCallThisFunction)
626 // The top-most function running on a goroutine
627 // returns to goexit+PCQuantum.
628 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
629 MOV ZERO, ZERO // NOP
630 JMP runtime·goexit1(SB) // does not return
631 // traceback from goexit1 must hit code range of goexit
632 MOV ZERO, ZERO // NOP
633
634
635 // This is called from .init_array and follows the platform, not the Go ABI.
636 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
637 // Use X31 as it is a scratch register in both the Go ABI and psABI.
638 MOV runtime·lastmoduledatap(SB), X31
639 MOV X10, moduledata_next(X31)
640 MOV X10, runtime·lastmoduledatap(SB)
641 RET
642
643 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
644 // See cgocall.go for more details.
645 TEXT ·cgocallback(SB),NOSPLIT,$24-24
646 NO_LOCAL_POINTERS
647
648 // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
649 // It is used to dropm while thread is exiting.
650 MOV fn+0(FP), X7
651 BNE ZERO, X7, loadg
652 // Restore the g from frame.
653 MOV frame+8(FP), g
654 JMP dropm
655
656 loadg:
657 // Load m and g from thread-local storage.
658 MOVBU runtime·iscgo(SB), X5
659 BEQ ZERO, X5, nocgo
660 CALL runtime·load_g(SB)
661 nocgo:
662
663 // If g is nil, Go did not create the current thread,
664 // or if this thread never called into Go on pthread platforms.
665 // Call needm to obtain one for temporary use.
666 // In this case, we're running on the thread stack, so there's
667 // lots of space, but the linker doesn't know. Hide the call from
668 // the linker analysis by using an indirect call.
669 BEQ ZERO, g, needm
670
671 MOV g_m(g), X5
672 MOV X5, savedm-8(SP)
673 JMP havem
674
675 needm:
676 MOV g, savedm-8(SP) // g is zero, so is m.
677 MOV $runtime·needAndBindM(SB), X6
678 JALR RA, X6
679
680 // Set m->sched.sp = SP, so that if a panic happens
681 // during the function we are about to execute, it will
682 // have a valid SP to run on the g0 stack.
683 // The next few lines (after the havem label)
684 // will save this SP onto the stack and then write
685 // the same SP back to m->sched.sp. That seems redundant,
686 // but if an unrecovered panic happens, unwindm will
687 // restore the g->sched.sp from the stack location
688 // and then systemstack will try to use it. If we don't set it here,
689 // that restored SP will be uninitialized (typically 0) and
690 // will not be usable.
691 MOV g_m(g), X5
692 MOV m_g0(X5), X6
693 MOV X2, (g_sched+gobuf_sp)(X6)
694
695 havem:
696 // Now there's a valid m, and we're running on its m->g0.
697 // Save current m->g0->sched.sp on stack and then set it to SP.
698 // Save current sp in m->g0->sched.sp in preparation for
699 // switch back to m->curg stack.
700 // NOTE: unwindm knows that the saved g->sched.sp is at 8(X2) aka savedsp-24(SP).
701 MOV m_g0(X5), X6
702 MOV (g_sched+gobuf_sp)(X6), X7
703 MOV X7, savedsp-24(SP) // must match frame size
704 MOV X2, (g_sched+gobuf_sp)(X6)
705
706 // Switch to m->curg stack and call runtime.cgocallbackg.
707 // Because we are taking over the execution of m->curg
708 // but *not* resuming what had been running, we need to
709 // save that information (m->curg->sched) so we can restore it.
710 // We can restore m->curg->sched.sp easily, because calling
711 // runtime.cgocallbackg leaves SP unchanged upon return.
712 // To save m->curg->sched.pc, we push it onto the curg stack and
713 // open a frame the same size as cgocallback's g0 frame.
714 // Once we switch to the curg stack, the pushed PC will appear
715 // to be the return PC of cgocallback, so that the traceback
716 // will seamlessly trace back into the earlier calls.
717 MOV m_curg(X5), g
718 CALL runtime·save_g(SB)
719 MOV (g_sched+gobuf_sp)(g), X6 // prepare stack as X6
720 MOV (g_sched+gobuf_pc)(g), X7
721 MOV X7, -(24+8)(X6) // "saved LR"; must match frame size
722 // Gather our arguments into registers.
723 MOV fn+0(FP), X7
724 MOV frame+8(FP), X8
725 MOV ctxt+16(FP), X9
726 MOV $-(24+8)(X6), X2 // switch stack; must match frame size
727 MOV X7, 8(X2)
728 MOV X8, 16(X2)
729 MOV X9, 24(X2)
730 CALL runtime·cgocallbackg(SB)
731
732 // Restore g->sched (== m->curg->sched) from saved values.
733 MOV 0(X2), X7
734 MOV X7, (g_sched+gobuf_pc)(g)
735 MOV $(24+8)(X2), X6 // must match frame size
736 MOV X6, (g_sched+gobuf_sp)(g)
737
738 // Switch back to m->g0's stack and restore m->g0->sched.sp.
739 // (Unlike m->curg, the g0 goroutine never uses sched.pc,
740 // so we do not have to restore it.)
741 MOV g_m(g), X5
742 MOV m_g0(X5), g
743 CALL runtime·save_g(SB)
744 MOV (g_sched+gobuf_sp)(g), X2
745 MOV savedsp-24(SP), X6 // must match frame size
746 MOV X6, (g_sched+gobuf_sp)(g)
747
748 // If the m on entry was nil, we called needm above to borrow an m,
749 // 1. for the duration of the call on non-pthread platforms,
750 // 2. or the duration of the C thread alive on pthread platforms.
751 // If the m on entry wasn't nil,
752 // 1. the thread might be a Go thread,
753 // 2. or it wasn't the first call from a C thread on pthread platforms,
754 // since then we skip dropm to reuse the m in the first call.
755 MOV savedm-8(SP), X5
756 BNE ZERO, X5, droppedm
757
758 // Skip dropm to reuse it in the next call, when a pthread key has been created.
759 MOV _cgo_pthread_key_created(SB), X5
760 // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
761 BEQ ZERO, X5, dropm
762 MOV (X5), X5
763 BNE ZERO, X5, droppedm
764
765 dropm:
766 MOV $runtime·dropm(SB), X6
767 JALR RA, X6
768 droppedm:
769
770 // Done!
771 RET
772
773 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
774 EBREAK
775 RET
776
777 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
778 EBREAK
779 RET
780
781 // void setg(G*); set g. for use by needm.
782 TEXT runtime·setg(SB), NOSPLIT, $0-8
783 MOV gg+0(FP), g
784 // This only happens if iscgo, so jump straight to save_g
785 CALL runtime·save_g(SB)
786 RET
787
788 TEXT ·checkASM(SB),NOSPLIT,$0-1
789 MOV $1, T0
790 MOV T0, ret+0(FP)
791 RET
792
793 // spillArgs stores return values from registers to a *internal/abi.RegArgs in X25.
794 TEXT ·spillArgs(SB),NOSPLIT,$0-0
795 MOV X10, (0*8)(X25)
796 MOV X11, (1*8)(X25)
797 MOV X12, (2*8)(X25)
798 MOV X13, (3*8)(X25)
799 MOV X14, (4*8)(X25)
800 MOV X15, (5*8)(X25)
801 MOV X16, (6*8)(X25)
802 MOV X17, (7*8)(X25)
803 MOV X8, (8*8)(X25)
804 MOV X9, (9*8)(X25)
805 MOV X18, (10*8)(X25)
806 MOV X19, (11*8)(X25)
807 MOV X20, (12*8)(X25)
808 MOV X21, (13*8)(X25)
809 MOV X22, (14*8)(X25)
810 MOV X23, (15*8)(X25)
811 MOVD F10, (16*8)(X25)
812 MOVD F11, (17*8)(X25)
813 MOVD F12, (18*8)(X25)
814 MOVD F13, (19*8)(X25)
815 MOVD F14, (20*8)(X25)
816 MOVD F15, (21*8)(X25)
817 MOVD F16, (22*8)(X25)
818 MOVD F17, (23*8)(X25)
819 MOVD F8, (24*8)(X25)
820 MOVD F9, (25*8)(X25)
821 MOVD F18, (26*8)(X25)
822 MOVD F19, (27*8)(X25)
823 MOVD F20, (28*8)(X25)
824 MOVD F21, (29*8)(X25)
825 MOVD F22, (30*8)(X25)
826 MOVD F23, (31*8)(X25)
827 RET
828
829 // unspillArgs loads args into registers from a *internal/abi.RegArgs in X25.
830 TEXT ·unspillArgs(SB),NOSPLIT,$0-0
831 MOV (0*8)(X25), X10
832 MOV (1*8)(X25), X11
833 MOV (2*8)(X25), X12
834 MOV (3*8)(X25), X13
835 MOV (4*8)(X25), X14
836 MOV (5*8)(X25), X15
837 MOV (6*8)(X25), X16
838 MOV (7*8)(X25), X17
839 MOV (8*8)(X25), X8
840 MOV (9*8)(X25), X9
841 MOV (10*8)(X25), X18
842 MOV (11*8)(X25), X19
843 MOV (12*8)(X25), X20
844 MOV (13*8)(X25), X21
845 MOV (14*8)(X25), X22
846 MOV (15*8)(X25), X23
847 MOVD (16*8)(X25), F10
848 MOVD (17*8)(X25), F11
849 MOVD (18*8)(X25), F12
850 MOVD (19*8)(X25), F13
851 MOVD (20*8)(X25), F14
852 MOVD (21*8)(X25), F15
853 MOVD (22*8)(X25), F16
854 MOVD (23*8)(X25), F17
855 MOVD (24*8)(X25), F8
856 MOVD (25*8)(X25), F9
857 MOVD (26*8)(X25), F18
858 MOVD (27*8)(X25), F19
859 MOVD (28*8)(X25), F20
860 MOVD (29*8)(X25), F21
861 MOVD (30*8)(X25), F22
862 MOVD (31*8)(X25), F23
863 RET
864
865 // gcWriteBarrier informs the GC about heap pointer writes.
866 //
867 // gcWriteBarrier does NOT follow the Go ABI. It accepts the
868 // number of bytes of buffer needed in X24, and returns a pointer
869 // to the buffer space in X24.
870 // It clobbers X31 aka T6 (the linker temp register - REG_TMP).
871 // The act of CALLing gcWriteBarrier will clobber RA (LR).
872 // It does not clobber any other general-purpose registers,
873 // but may clobber others (e.g., floating point registers).
874 TEXT gcWriteBarrier<>(SB),NOSPLIT,$208
875 // Save the registers clobbered by the fast path.
876 MOV A0, 24*8(X2)
877 MOV A1, 25*8(X2)
878 retry:
879 MOV g_m(g), A0
880 MOV m_p(A0), A0
881 MOV (p_wbBuf+wbBuf_next)(A0), A1
882 MOV (p_wbBuf+wbBuf_end)(A0), T6 // T6 is linker temp register (REG_TMP)
883 // Increment wbBuf.next position.
884 ADD X24, A1
885 // Is the buffer full?
886 BLTU T6, A1, flush
887 // Commit to the larger buffer.
888 MOV A1, (p_wbBuf+wbBuf_next)(A0)
889 // Make the return value (the original next position)
890 SUB X24, A1, X24
891 // Restore registers.
892 MOV 24*8(X2), A0
893 MOV 25*8(X2), A1
894 RET
895
896 flush:
897 // Save all general purpose registers since these could be
898 // clobbered by wbBufFlush and were not saved by the caller.
899 MOV T0, 1*8(X2)
900 MOV T1, 2*8(X2)
901 // X0 is zero register
902 // X1 is LR, saved by prologue
903 // X2 is SP
904 // X3 is GP
905 // X4 is TP
906 MOV X7, 3*8(X2)
907 MOV X8, 4*8(X2)
908 MOV X9, 5*8(X2)
909 // X10 already saved (A0)
910 // X11 already saved (A1)
911 MOV X12, 6*8(X2)
912 MOV X13, 7*8(X2)
913 MOV X14, 8*8(X2)
914 MOV X15, 9*8(X2)
915 MOV X16, 10*8(X2)
916 MOV X17, 11*8(X2)
917 MOV X18, 12*8(X2)
918 MOV X19, 13*8(X2)
919 MOV X20, 14*8(X2)
920 MOV X21, 15*8(X2)
921 MOV X22, 16*8(X2)
922 MOV X23, 17*8(X2)
923 MOV X24, 18*8(X2)
924 MOV X25, 19*8(X2)
925 MOV X26, 20*8(X2)
926 // X27 is g.
927 MOV X28, 21*8(X2)
928 MOV X29, 22*8(X2)
929 MOV X30, 23*8(X2)
930 // X31 is tmp register.
931
932 CALL runtime·wbBufFlush(SB)
933
934 MOV 1*8(X2), T0
935 MOV 2*8(X2), T1
936 MOV 3*8(X2), X7
937 MOV 4*8(X2), X8
938 MOV 5*8(X2), X9
939 MOV 6*8(X2), X12
940 MOV 7*8(X2), X13
941 MOV 8*8(X2), X14
942 MOV 9*8(X2), X15
943 MOV 10*8(X2), X16
944 MOV 11*8(X2), X17
945 MOV 12*8(X2), X18
946 MOV 13*8(X2), X19
947 MOV 14*8(X2), X20
948 MOV 15*8(X2), X21
949 MOV 16*8(X2), X22
950 MOV 17*8(X2), X23
951 MOV 18*8(X2), X24
952 MOV 19*8(X2), X25
953 MOV 20*8(X2), X26
954 MOV 21*8(X2), X28
955 MOV 22*8(X2), X29
956 MOV 23*8(X2), X30
957
958 JMP retry
959
960 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
961 MOV $8, X24
962 JMP gcWriteBarrier<>(SB)
963 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
964 MOV $16, X24
965 JMP gcWriteBarrier<>(SB)
966 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
967 MOV $24, X24
968 JMP gcWriteBarrier<>(SB)
969 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
970 MOV $32, X24
971 JMP gcWriteBarrier<>(SB)
972 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
973 MOV $40, X24
974 JMP gcWriteBarrier<>(SB)
975 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
976 MOV $48, X24
977 JMP gcWriteBarrier<>(SB)
978 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
979 MOV $56, X24
980 JMP gcWriteBarrier<>(SB)
981 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
982 MOV $64, X24
983 JMP gcWriteBarrier<>(SB)
984
985 TEXT runtime·panicBounds<ABIInternal>(SB),NOSPLIT,$144-0
986 NO_LOCAL_POINTERS
987 // Save all 16 int registers that could have an index in them.
988 // They may be pointers, but if they are they are dead.
989 // Skip X0 aka ZERO, X1 aka LR, X2 aka SP, X3 aka GP, X4 aka TP.
990 MOV X5, 24(X2)
991 MOV X6, 32(X2)
992 MOV X7, 40(X2)
993 MOV X8, 48(X2)
994 MOV X9, 56(X2)
995 MOV X10, 64(X2)
996 MOV X11, 72(X2)
997 MOV X12, 80(X2)
998 MOV X13, 88(X2)
999 MOV X14, 96(X2)
1000 MOV X15, 104(X2)
1001 MOV X16, 112(X2)
1002 MOV X17, 120(X2)
1003 MOV X18, 128(X2)
1004 MOV X19, 136(X2)
1005 MOV X20, 144(X2)
1006
1007 MOV X1, X10 // PC immediately after call to panicBounds
1008 ADD $24, X2, X11 // pointer to save area
1009 CALL runtime·panicBounds64<ABIInternal>(SB)
1010 RET
1011
1012 DATA runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB)
1013 GLOBL runtime·mainPC(SB),RODATA,$8
1014
View as plain text