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 // func rt0_go()
10 TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
11 // X2 = stack; A0 = argc; A1 = argv
12 ADD $-24, X2
13 MOV A0, 8(X2) // argc
14 MOV A1, 16(X2) // argv
15
16 // create istack out of the given (operating system) stack.
17 // _cgo_init may update stackguard.
18 MOV $runtime·g0(SB), g
19 MOV $(-64*1024), T0
20 ADD T0, X2, T1
21 MOV T1, g_stackguard0(g)
22 MOV T1, g_stackguard1(g)
23 MOV T1, (g_stack+stack_lo)(g)
24 MOV X2, (g_stack+stack_hi)(g)
25
26 // if there is a _cgo_init, call it using the gcc ABI.
27 MOV _cgo_init(SB), T0
28 BEQ T0, ZERO, nocgo
29
30 MOV ZERO, A3 // arg 3: not used
31 MOV ZERO, A2 // arg 2: not used
32 MOV $setg_gcc<>(SB), A1 // arg 1: setg
33 MOV g, A0 // arg 0: G
34 JALR RA, T0
35
36 nocgo:
37 // update stackguard after _cgo_init
38 MOV (g_stack+stack_lo)(g), T0
39 ADD $const__StackGuard, T0
40 MOV T0, g_stackguard0(g)
41 MOV T0, g_stackguard1(g)
42
43 // set the per-goroutine and per-mach "registers"
44 MOV $runtime·m0(SB), T0
45
46 // save m->g0 = g0
47 MOV g, m_g0(T0)
48 // save m0 to g0->m
49 MOV T0, g_m(g)
50
51 CALL runtime·check(SB)
52
53 // args are already prepared
54 CALL runtime·args(SB)
55 CALL runtime·osinit(SB)
56 CALL runtime·schedinit(SB)
57
58 // create a new goroutine to start program
59 MOV $runtime·mainPC(SB), T0 // entry
60 ADD $-16, X2
61 MOV T0, 8(X2)
62 MOV ZERO, 0(X2)
63 CALL runtime·newproc(SB)
64 ADD $16, X2
65
66 // start this M
67 CALL runtime·mstart(SB)
68
69 WORD $0 // crash if reached
70 RET
71
72 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
73 CALL runtime·mstart0(SB)
74 RET // not reached
75
76 // void setg_gcc(G*); set g called from gcc with g in A0
77 TEXT setg_gcc<>(SB),NOSPLIT,$0-0
78 MOV A0, g
79 CALL runtime·save_g(SB)
80 RET
81
82 // func cputicks() int64
83 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
84 // RDTIME to emulate cpu ticks
85 // RDCYCLE reads counter that is per HART(core) based
86 // according to the riscv manual, see issue 46737
87 RDTIME A0
88 MOV A0, ret+0(FP)
89 RET
90
91 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
92 // of the G stack. We need to distinguish the routine that
93 // lives at the bottom of the G stack from the one that lives
94 // at the top of the system stack because the one at the top of
95 // the system stack terminates the stack walk (see topofstack()).
96 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
97 UNDEF
98 JALR RA, ZERO // make sure this function is not leaf
99 RET
100
101 // func systemstack(fn func())
102 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
103 MOV fn+0(FP), CTXT // CTXT = fn
104 MOV g_m(g), T0 // T0 = m
105
106 MOV m_gsignal(T0), T1 // T1 = gsignal
107 BEQ g, T1, noswitch
108
109 MOV m_g0(T0), T1 // T1 = g0
110 BEQ g, T1, noswitch
111
112 MOV m_curg(T0), T2
113 BEQ g, T2, switch
114
115 // Bad: g is not gsignal, not g0, not curg. What is it?
116 // Hide call from linker nosplit analysis.
117 MOV $runtime·badsystemstack(SB), T1
118 JALR RA, T1
119
120 switch:
121 // save our state in g->sched. Pretend to
122 // be systemstack_switch if the G stack is scanned.
123 CALL gosave_systemstack_switch<>(SB)
124
125 // switch to g0
126 MOV T1, g
127 CALL runtime·save_g(SB)
128 MOV (g_sched+gobuf_sp)(g), T0
129 MOV T0, X2
130
131 // call target function
132 MOV 0(CTXT), T1 // code pointer
133 JALR RA, T1
134
135 // switch back to g
136 MOV g_m(g), T0
137 MOV m_curg(T0), g
138 CALL runtime·save_g(SB)
139 MOV (g_sched+gobuf_sp)(g), X2
140 MOV ZERO, (g_sched+gobuf_sp)(g)
141 RET
142
143 noswitch:
144 // already on m stack, just call directly
145 // Using a tail call here cleans up tracebacks since we won't stop
146 // at an intermediate systemstack.
147 MOV 0(CTXT), T1 // code pointer
148 ADD $8, X2
149 JMP (T1)
150
151 TEXT runtime·getcallerpc(SB),NOSPLIT|NOFRAME,$0-8
152 MOV 0(X2), T0 // LR saved by caller
153 MOV T0, ret+0(FP)
154 RET
155
156 /*
157 * support for morestack
158 */
159
160 // Called during function prolog when more stack is needed.
161 // Caller has already loaded:
162 // R1: framesize, R2: argsize, R3: LR
163 //
164 // The traceback routines see morestack on a g0 as being
165 // the top of a stack (for example, morestack calling newstack
166 // calling the scheduler calling newm calling gc), so we must
167 // record an argument size. For that purpose, it has no arguments.
168
169 // func morestack()
170 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
171 // Cannot grow scheduler stack (m->g0).
172 MOV g_m(g), A0
173 MOV m_g0(A0), A1
174 BNE g, A1, 3(PC)
175 CALL runtime·badmorestackg0(SB)
176 CALL runtime·abort(SB)
177
178 // Cannot grow signal stack (m->gsignal).
179 MOV m_gsignal(A0), A1
180 BNE g, A1, 3(PC)
181 CALL runtime·badmorestackgsignal(SB)
182 CALL runtime·abort(SB)
183
184 // Called from f.
185 // Set g->sched to context in f.
186 MOV X2, (g_sched+gobuf_sp)(g)
187 MOV T0, (g_sched+gobuf_pc)(g)
188 MOV RA, (g_sched+gobuf_lr)(g)
189 MOV CTXT, (g_sched+gobuf_ctxt)(g)
190
191 // Called from f.
192 // Set m->morebuf to f's caller.
193 MOV RA, (m_morebuf+gobuf_pc)(A0) // f's caller's PC
194 MOV X2, (m_morebuf+gobuf_sp)(A0) // f's caller's SP
195 MOV g, (m_morebuf+gobuf_g)(A0)
196
197 // Call newstack on m->g0's stack.
198 MOV m_g0(A0), g
199 CALL runtime·save_g(SB)
200 MOV (g_sched+gobuf_sp)(g), X2
201 // Create a stack frame on g0 to call newstack.
202 MOV ZERO, -8(X2) // Zero saved LR in frame
203 ADD $-8, X2
204 CALL runtime·newstack(SB)
205
206 // Not reached, but make sure the return PC from the call to newstack
207 // is still in this function, and not the beginning of the next.
208 UNDEF
209
210 // func morestack_noctxt()
211 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
212 MOV ZERO, CTXT
213 JMP runtime·morestack(SB)
214
215 // AES hashing not implemented for riscv64
216 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
217 JMP runtime·memhashFallback(SB)
218 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
219 JMP runtime·strhashFallback(SB)
220 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
221 JMP runtime·memhash32Fallback(SB)
222 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
223 JMP runtime·memhash64Fallback(SB)
224
225 // func return0()
226 TEXT runtime·return0(SB), NOSPLIT, $0
227 MOV $0, A0
228 RET
229
230 // restore state from Gobuf; longjmp
231
232 // func gogo(buf *gobuf)
233 TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
234 MOV buf+0(FP), T0
235 MOV gobuf_g(T0), T1
236 MOV 0(T1), ZERO // make sure g != nil
237 JMP gogo<>(SB)
238
239 TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
240 MOV T1, g
241 CALL runtime·save_g(SB)
242
243 MOV gobuf_sp(T0), X2
244 MOV gobuf_lr(T0), RA
245 MOV gobuf_ret(T0), A0
246 MOV gobuf_ctxt(T0), CTXT
247 MOV ZERO, gobuf_sp(T0)
248 MOV ZERO, gobuf_ret(T0)
249 MOV ZERO, gobuf_lr(T0)
250 MOV ZERO, gobuf_ctxt(T0)
251 MOV gobuf_pc(T0), T0
252 JALR ZERO, T0
253
254 // func procyield(cycles uint32)
255 TEXT runtime·procyield(SB),NOSPLIT,$0-0
256 RET
257
258 // Switch to m->g0's stack, call fn(g).
259 // Fn must never return. It should gogo(&g->sched)
260 // to keep running g.
261
262 // func mcall(fn func(*g))
263 TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
264 // Save caller state in g->sched
265 MOV X2, (g_sched+gobuf_sp)(g)
266 MOV RA, (g_sched+gobuf_pc)(g)
267 MOV ZERO, (g_sched+gobuf_lr)(g)
268
269 // Switch to m->g0 & its stack, call fn.
270 MOV g, T0
271 MOV g_m(g), T1
272 MOV m_g0(T1), g
273 CALL runtime·save_g(SB)
274 BNE g, T0, 2(PC)
275 JMP runtime·badmcall(SB)
276 MOV fn+0(FP), CTXT // context
277 MOV 0(CTXT), T1 // code pointer
278 MOV (g_sched+gobuf_sp)(g), X2 // sp = m->g0->sched.sp
279 ADD $-16, X2
280 MOV T0, 8(X2)
281 MOV ZERO, 0(X2)
282 JALR RA, T1
283 JMP runtime·badmcall2(SB)
284
285 // Save state of caller into g->sched,
286 // but using fake PC from systemstack_switch.
287 // Must only be called from functions with no locals ($0)
288 // or else unwinding from systemstack_switch is incorrect.
289 // Smashes X31.
290 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
291 MOV $runtime·systemstack_switch(SB), X31
292 ADD $8, X31 // get past prologue
293 MOV X31, (g_sched+gobuf_pc)(g)
294 MOV X2, (g_sched+gobuf_sp)(g)
295 MOV ZERO, (g_sched+gobuf_lr)(g)
296 MOV ZERO, (g_sched+gobuf_ret)(g)
297 // Assert ctxt is zero. See func save.
298 MOV (g_sched+gobuf_ctxt)(g), X31
299 BEQ ZERO, X31, 2(PC)
300 CALL runtime·abort(SB)
301 RET
302
303 // func asmcgocall(fn, arg unsafe.Pointer) int32
304 // Call fn(arg) on the scheduler stack,
305 // aligned appropriately for the gcc ABI.
306 // See cgocall.go for more details.
307 TEXT ·asmcgocall(SB),NOSPLIT,$0-20
308 MOV fn+0(FP), X5
309 MOV arg+8(FP), X10
310
311 MOV X2, X8 // save original stack pointer
312 MOV g, X9
313
314 // Figure out if we need to switch to m->g0 stack.
315 // We get called to create new OS threads too, and those
316 // come in on the m->g0 stack already. Or we might already
317 // be on the m->gsignal stack.
318 MOV g_m(g), X6
319 MOV m_gsignal(X6), X7
320 BEQ X7, g, g0
321 MOV m_g0(X6), X7
322 BEQ X7, g, g0
323
324 CALL gosave_systemstack_switch<>(SB)
325 MOV X7, g
326 CALL runtime·save_g(SB)
327 MOV (g_sched+gobuf_sp)(g), X2
328
329 // Now on a scheduling stack (a pthread-created stack).
330 g0:
331 // Save room for two of our pointers.
332 ADD $-16, X2
333 MOV X9, 0(X2) // save old g on stack
334 MOV (g_stack+stack_hi)(X9), X9
335 SUB X8, X9, X8
336 MOV X8, 8(X2) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
337
338 JALR RA, (X5)
339
340 // Restore g, stack pointer. X10 is return value.
341 MOV 0(X2), g
342 CALL runtime·save_g(SB)
343 MOV (g_stack+stack_hi)(g), X5
344 MOV 8(X2), X6
345 SUB X6, X5, X6
346 MOV X6, X2
347
348 MOVW X10, ret+16(FP)
349 RET
350
351 // func asminit()
352 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
353 RET
354
355 // reflectcall: call a function with the given argument list
356 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
357 // we don't have variable-sized frames, so we use a small number
358 // of constant-sized-frame functions to encode a few bits of size in the pc.
359 // Caution: ugly multiline assembly macros in your future!
360
361 #define DISPATCH(NAME,MAXSIZE) \
362 MOV $MAXSIZE, T1 \
363 BLTU T1, T0, 3(PC) \
364 MOV $NAME(SB), T2; \
365 JALR ZERO, T2
366 // Note: can't just "BR NAME(SB)" - bad inlining results.
367
368 // func call(stackArgsType *rtype, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
369 TEXT reflect·call(SB), NOSPLIT, $0-0
370 JMP ·reflectcall(SB)
371
372 // func call(stackArgsType *_type, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
373 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
374 MOVWU frameSize+32(FP), T0
375 DISPATCH(runtime·call16, 16)
376 DISPATCH(runtime·call32, 32)
377 DISPATCH(runtime·call64, 64)
378 DISPATCH(runtime·call128, 128)
379 DISPATCH(runtime·call256, 256)
380 DISPATCH(runtime·call512, 512)
381 DISPATCH(runtime·call1024, 1024)
382 DISPATCH(runtime·call2048, 2048)
383 DISPATCH(runtime·call4096, 4096)
384 DISPATCH(runtime·call8192, 8192)
385 DISPATCH(runtime·call16384, 16384)
386 DISPATCH(runtime·call32768, 32768)
387 DISPATCH(runtime·call65536, 65536)
388 DISPATCH(runtime·call131072, 131072)
389 DISPATCH(runtime·call262144, 262144)
390 DISPATCH(runtime·call524288, 524288)
391 DISPATCH(runtime·call1048576, 1048576)
392 DISPATCH(runtime·call2097152, 2097152)
393 DISPATCH(runtime·call4194304, 4194304)
394 DISPATCH(runtime·call8388608, 8388608)
395 DISPATCH(runtime·call16777216, 16777216)
396 DISPATCH(runtime·call33554432, 33554432)
397 DISPATCH(runtime·call67108864, 67108864)
398 DISPATCH(runtime·call134217728, 134217728)
399 DISPATCH(runtime·call268435456, 268435456)
400 DISPATCH(runtime·call536870912, 536870912)
401 DISPATCH(runtime·call1073741824, 1073741824)
402 MOV $runtime·badreflectcall(SB), T2
403 JALR ZERO, T2
404
405 #define CALLFN(NAME,MAXSIZE) \
406 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
407 NO_LOCAL_POINTERS; \
408 /* copy arguments to stack */ \
409 MOV stackArgs+16(FP), A1; \
410 MOVWU stackArgsSize+24(FP), A2; \
411 MOV X2, A3; \
412 ADD $8, A3; \
413 ADD A3, A2; \
414 BEQ A3, A2, 6(PC); \
415 MOVBU (A1), A4; \
416 ADD $1, A1; \
417 MOVB A4, (A3); \
418 ADD $1, A3; \
419 JMP -5(PC); \
420 /* call function */ \
421 MOV f+8(FP), CTXT; \
422 MOV (CTXT), A4; \
423 PCDATA $PCDATA_StackMapIndex, $0; \
424 JALR RA, A4; \
425 /* copy return values back */ \
426 MOV stackArgsType+0(FP), A5; \
427 MOV stackArgs+16(FP), A1; \
428 MOVWU stackArgsSize+24(FP), A2; \
429 MOVWU stackRetOffset+28(FP), A4; \
430 ADD $8, X2, A3; \
431 ADD A4, A3; \
432 ADD A4, A1; \
433 SUB A4, A2; \
434 CALL callRet<>(SB); \
435 RET
436
437 // callRet copies return values back at the end of call*. This is a
438 // separate function so it can allocate stack space for the arguments
439 // to reflectcallmove. It does not follow the Go ABI; it expects its
440 // arguments in registers.
441 TEXT callRet<>(SB), NOSPLIT, $40-0
442 MOV A5, 8(X2)
443 MOV A1, 16(X2)
444 MOV A3, 24(X2)
445 MOV A2, 32(X2)
446 MOV ZERO, 40(X2)
447 CALL runtime·reflectcallmove(SB)
448 RET
449
450 CALLFN(·call16, 16)
451 CALLFN(·call32, 32)
452 CALLFN(·call64, 64)
453 CALLFN(·call128, 128)
454 CALLFN(·call256, 256)
455 CALLFN(·call512, 512)
456 CALLFN(·call1024, 1024)
457 CALLFN(·call2048, 2048)
458 CALLFN(·call4096, 4096)
459 CALLFN(·call8192, 8192)
460 CALLFN(·call16384, 16384)
461 CALLFN(·call32768, 32768)
462 CALLFN(·call65536, 65536)
463 CALLFN(·call131072, 131072)
464 CALLFN(·call262144, 262144)
465 CALLFN(·call524288, 524288)
466 CALLFN(·call1048576, 1048576)
467 CALLFN(·call2097152, 2097152)
468 CALLFN(·call4194304, 4194304)
469 CALLFN(·call8388608, 8388608)
470 CALLFN(·call16777216, 16777216)
471 CALLFN(·call33554432, 33554432)
472 CALLFN(·call67108864, 67108864)
473 CALLFN(·call134217728, 134217728)
474 CALLFN(·call268435456, 268435456)
475 CALLFN(·call536870912, 536870912)
476 CALLFN(·call1073741824, 1073741824)
477
478 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
479 // Must obey the gcc calling convention.
480 TEXT _cgo_topofstack(SB),NOSPLIT,$8
481 // g (X27) and REG_TMP (X31) might be clobbered by load_g.
482 // X27 is callee-save in the gcc calling convention, so save it.
483 MOV g, savedX27-8(SP)
484
485 CALL runtime·load_g(SB)
486 MOV g_m(g), X5
487 MOV m_curg(X5), X5
488 MOV (g_stack+stack_hi)(X5), X10 // return value in X10
489
490 MOV savedX27-8(SP), g
491 RET
492
493 // func goexit(neverCallThisFunction)
494 // The top-most function running on a goroutine
495 // returns to goexit+PCQuantum.
496 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
497 MOV ZERO, ZERO // NOP
498 JMP runtime·goexit1(SB) // does not return
499 // traceback from goexit1 must hit code range of goexit
500 MOV ZERO, ZERO // NOP
501
502 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
503 // See cgocall.go for more details.
504 TEXT ·cgocallback(SB),NOSPLIT,$24-24
505 NO_LOCAL_POINTERS
506
507 // Load m and g from thread-local storage.
508 MOVBU runtime·iscgo(SB), X5
509 BEQ ZERO, X5, nocgo
510 CALL runtime·load_g(SB)
511 nocgo:
512
513 // If g is nil, Go did not create the current thread.
514 // Call needm to obtain one for temporary use.
515 // In this case, we're running on the thread stack, so there's
516 // lots of space, but the linker doesn't know. Hide the call from
517 // the linker analysis by using an indirect call.
518 BEQ ZERO, g, needm
519
520 MOV g_m(g), X5
521 MOV X5, savedm-8(SP)
522 JMP havem
523
524 needm:
525 MOV g, savedm-8(SP) // g is zero, so is m.
526 MOV $runtime·needm(SB), X6
527 JALR RA, X6
528
529 // Set m->sched.sp = SP, so that if a panic happens
530 // during the function we are about to execute, it will
531 // have a valid SP to run on the g0 stack.
532 // The next few lines (after the havem label)
533 // will save this SP onto the stack and then write
534 // the same SP back to m->sched.sp. That seems redundant,
535 // but if an unrecovered panic happens, unwindm will
536 // restore the g->sched.sp from the stack location
537 // and then systemstack will try to use it. If we don't set it here,
538 // that restored SP will be uninitialized (typically 0) and
539 // will not be usable.
540 MOV g_m(g), X5
541 MOV m_g0(X5), X6
542 MOV X2, (g_sched+gobuf_sp)(X6)
543
544 havem:
545 // Now there's a valid m, and we're running on its m->g0.
546 // Save current m->g0->sched.sp on stack and then set it to SP.
547 // Save current sp in m->g0->sched.sp in preparation for
548 // switch back to m->curg stack.
549 // NOTE: unwindm knows that the saved g->sched.sp is at 8(X2) aka savedsp-24(SP).
550 MOV m_g0(X5), X6
551 MOV (g_sched+gobuf_sp)(X6), X7
552 MOV X7, savedsp-24(SP) // must match frame size
553 MOV X2, (g_sched+gobuf_sp)(X6)
554
555 // Switch to m->curg stack and call runtime.cgocallbackg.
556 // Because we are taking over the execution of m->curg
557 // but *not* resuming what had been running, we need to
558 // save that information (m->curg->sched) so we can restore it.
559 // We can restore m->curg->sched.sp easily, because calling
560 // runtime.cgocallbackg leaves SP unchanged upon return.
561 // To save m->curg->sched.pc, we push it onto the curg stack and
562 // open a frame the same size as cgocallback's g0 frame.
563 // Once we switch to the curg stack, the pushed PC will appear
564 // to be the return PC of cgocallback, so that the traceback
565 // will seamlessly trace back into the earlier calls.
566 MOV m_curg(X5), g
567 CALL runtime·save_g(SB)
568 MOV (g_sched+gobuf_sp)(g), X6 // prepare stack as X6
569 MOV (g_sched+gobuf_pc)(g), X7
570 MOV X7, -(24+8)(X6) // "saved LR"; must match frame size
571 // Gather our arguments into registers.
572 MOV fn+0(FP), X7
573 MOV frame+8(FP), X8
574 MOV ctxt+16(FP), X9
575 MOV $-(24+8)(X6), X2 // switch stack; must match frame size
576 MOV X7, 8(X2)
577 MOV X8, 16(X2)
578 MOV X9, 24(X2)
579 CALL runtime·cgocallbackg(SB)
580
581 // Restore g->sched (== m->curg->sched) from saved values.
582 MOV 0(X2), X7
583 MOV X7, (g_sched+gobuf_pc)(g)
584 MOV $(24+8)(X2), X6 // must match frame size
585 MOV X6, (g_sched+gobuf_sp)(g)
586
587 // Switch back to m->g0's stack and restore m->g0->sched.sp.
588 // (Unlike m->curg, the g0 goroutine never uses sched.pc,
589 // so we do not have to restore it.)
590 MOV g_m(g), X5
591 MOV m_g0(X5), g
592 CALL runtime·save_g(SB)
593 MOV (g_sched+gobuf_sp)(g), X2
594 MOV savedsp-24(SP), X6 // must match frame size
595 MOV X6, (g_sched+gobuf_sp)(g)
596
597 // If the m on entry was nil, we called needm above to borrow an m
598 // for the duration of the call. Since the call is over, return it with dropm.
599 MOV savedm-8(SP), X5
600 BNE ZERO, X5, droppedm
601 MOV $runtime·dropm(SB), X6
602 JALR RA, X6
603 droppedm:
604
605 // Done!
606 RET
607
608 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
609 EBREAK
610 RET
611
612 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
613 EBREAK
614 RET
615
616 // void setg(G*); set g. for use by needm.
617 TEXT runtime·setg(SB), NOSPLIT, $0-8
618 MOV gg+0(FP), g
619 // This only happens if iscgo, so jump straight to save_g
620 CALL runtime·save_g(SB)
621 RET
622
623 TEXT ·checkASM(SB),NOSPLIT,$0-1
624 MOV $1, T0
625 MOV T0, ret+0(FP)
626 RET
627
628 // gcWriteBarrier performs a heap pointer write and informs the GC.
629 //
630 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
631 // - T0 is the destination of the write
632 // - T1 is the value being written at T0.
633 // It clobbers R30 (the linker temp register - REG_TMP).
634 // The act of CALLing gcWriteBarrier will clobber RA (LR).
635 // It does not clobber any other general-purpose registers,
636 // but may clobber others (e.g., floating point registers).
637 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$208
638 // Save the registers clobbered by the fast path.
639 MOV A0, 24*8(X2)
640 MOV A1, 25*8(X2)
641 MOV g_m(g), A0
642 MOV m_p(A0), A0
643 MOV (p_wbBuf+wbBuf_next)(A0), A1
644 // Increment wbBuf.next position.
645 ADD $16, A1
646 MOV A1, (p_wbBuf+wbBuf_next)(A0)
647 MOV (p_wbBuf+wbBuf_end)(A0), A0
648 MOV A0, T6 // T6 is linker temp register (REG_TMP)
649 // Record the write.
650 MOV T1, -16(A1) // Record value
651 MOV (T0), A0 // TODO: This turns bad writes into bad reads.
652 MOV A0, -8(A1) // Record *slot
653 // Is the buffer full?
654 BEQ A1, T6, flush
655 ret:
656 MOV 24*8(X2), A0
657 MOV 25*8(X2), A1
658 // Do the write.
659 MOV T1, (T0)
660 RET
661
662 flush:
663 // Save all general purpose registers since these could be
664 // clobbered by wbBufFlush and were not saved by the caller.
665 MOV T0, 1*8(X2) // Also first argument to wbBufFlush
666 MOV T1, 2*8(X2) // Also second argument to wbBufFlush
667 // X0 is zero register
668 // X1 is LR, saved by prologue
669 // X2 is SP
670 // X3 is GP
671 // X4 is TP
672 // X5 is first arg to wbBufFlush (T0)
673 // X6 is second arg to wbBufFlush (T1)
674 MOV X7, 3*8(X2)
675 MOV X8, 4*8(X2)
676 MOV X9, 5*8(X2)
677 // X10 already saved (A0)
678 // X11 already saved (A1)
679 MOV X12, 6*8(X2)
680 MOV X13, 7*8(X2)
681 MOV X14, 8*8(X2)
682 MOV X15, 9*8(X2)
683 MOV X16, 10*8(X2)
684 MOV X17, 11*8(X2)
685 MOV X18, 12*8(X2)
686 MOV X19, 13*8(X2)
687 MOV X20, 14*8(X2)
688 MOV X21, 15*8(X2)
689 MOV X22, 16*8(X2)
690 MOV X23, 17*8(X2)
691 MOV X24, 18*8(X2)
692 MOV X25, 19*8(X2)
693 MOV X26, 20*8(X2)
694 // X27 is g.
695 MOV X28, 21*8(X2)
696 MOV X29, 22*8(X2)
697 MOV X30, 23*8(X2)
698 // X31 is tmp register.
699
700 // This takes arguments T0 and T1.
701 CALL runtime·wbBufFlush(SB)
702
703 MOV 1*8(X2), T0
704 MOV 2*8(X2), T1
705 MOV 3*8(X2), X7
706 MOV 4*8(X2), X8
707 MOV 5*8(X2), X9
708 MOV 6*8(X2), X12
709 MOV 7*8(X2), X13
710 MOV 8*8(X2), X14
711 MOV 9*8(X2), X15
712 MOV 10*8(X2), X16
713 MOV 11*8(X2), X17
714 MOV 12*8(X2), X18
715 MOV 13*8(X2), X19
716 MOV 14*8(X2), X20
717 MOV 15*8(X2), X21
718 MOV 16*8(X2), X22
719 MOV 17*8(X2), X23
720 MOV 18*8(X2), X24
721 MOV 19*8(X2), X25
722 MOV 20*8(X2), X26
723 MOV 21*8(X2), X28
724 MOV 22*8(X2), X29
725 MOV 23*8(X2), X30
726
727 JMP ret
728
729 // Note: these functions use a special calling convention to save generated code space.
730 // Arguments are passed in registers, but the space for those arguments are allocated
731 // in the caller's stack frame. These stubs write the args into that stack space and
732 // then tail call to the corresponding runtime handler.
733 // The tail call makes these stubs disappear in backtraces.
734 TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
735 MOV T0, x+0(FP)
736 MOV T1, y+8(FP)
737 JMP runtime·goPanicIndex(SB)
738 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
739 MOV T0, x+0(FP)
740 MOV T1, y+8(FP)
741 JMP runtime·goPanicIndexU(SB)
742 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
743 MOV T1, x+0(FP)
744 MOV T2, y+8(FP)
745 JMP runtime·goPanicSliceAlen(SB)
746 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
747 MOV T1, x+0(FP)
748 MOV T2, y+8(FP)
749 JMP runtime·goPanicSliceAlenU(SB)
750 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
751 MOV T1, x+0(FP)
752 MOV T2, y+8(FP)
753 JMP runtime·goPanicSliceAcap(SB)
754 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
755 MOV T1, x+0(FP)
756 MOV T2, y+8(FP)
757 JMP runtime·goPanicSliceAcapU(SB)
758 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
759 MOV T0, x+0(FP)
760 MOV T1, y+8(FP)
761 JMP runtime·goPanicSliceB(SB)
762 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
763 MOV T0, x+0(FP)
764 MOV T1, y+8(FP)
765 JMP runtime·goPanicSliceBU(SB)
766 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
767 MOV T2, x+0(FP)
768 MOV T3, y+8(FP)
769 JMP runtime·goPanicSlice3Alen(SB)
770 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
771 MOV T2, x+0(FP)
772 MOV T3, y+8(FP)
773 JMP runtime·goPanicSlice3AlenU(SB)
774 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
775 MOV T2, x+0(FP)
776 MOV T3, y+8(FP)
777 JMP runtime·goPanicSlice3Acap(SB)
778 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
779 MOV T2, x+0(FP)
780 MOV T3, y+8(FP)
781 JMP runtime·goPanicSlice3AcapU(SB)
782 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
783 MOV T1, x+0(FP)
784 MOV T2, y+8(FP)
785 JMP runtime·goPanicSlice3B(SB)
786 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
787 MOV T1, x+0(FP)
788 MOV T2, y+8(FP)
789 JMP runtime·goPanicSlice3BU(SB)
790 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
791 MOV T0, x+0(FP)
792 MOV T1, y+8(FP)
793 JMP runtime·goPanicSlice3C(SB)
794 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
795 MOV T0, x+0(FP)
796 MOV T1, y+8(FP)
797 JMP runtime·goPanicSlice3CU(SB)
798 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
799 MOV T2, x+0(FP)
800 MOV T3, y+8(FP)
801 JMP runtime·goPanicSliceConvert(SB)
802
803 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
804 GLOBL runtime·mainPC(SB),RODATA,$8
805
View as plain text