]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_arm.s
runtime/cgo: store M for C-created thread in pthread key
[gostls13.git] / src / runtime / asm_arm.s
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "go_asm.h"
6 #include "go_tls.h"
7 #include "funcdata.h"
8 #include "textflag.h"
9
10 // _rt0_arm is common startup code for most ARM systems when using
11 // internal linking. This is the entry point for the program from the
12 // kernel for an ordinary -buildmode=exe program. The stack holds the
13 // number of arguments and the C-style argv.
14 TEXT _rt0_arm(SB),NOSPLIT|NOFRAME,$0
15         MOVW    (R13), R0       // argc
16         MOVW    $4(R13), R1             // argv
17         B       runtime·rt0_go(SB)
18
19 // main is common startup code for most ARM systems when using
20 // external linking. The C startup code will call the symbol "main"
21 // passing argc and argv in the usual C ABI registers R0 and R1.
22 TEXT main(SB),NOSPLIT|NOFRAME,$0
23         B       runtime·rt0_go(SB)
24
25 // _rt0_arm_lib is common startup code for most ARM systems when
26 // using -buildmode=c-archive or -buildmode=c-shared. The linker will
27 // arrange to invoke this function as a global constructor (for
28 // c-archive) or when the shared library is loaded (for c-shared).
29 // We expect argc and argv to be passed in the usual C ABI registers
30 // R0 and R1.
31 TEXT _rt0_arm_lib(SB),NOSPLIT,$104
32         // Preserve callee-save registers. Raspberry Pi's dlopen(), for example,
33         // actually cares that R11 is preserved.
34         MOVW    R4, 12(R13)
35         MOVW    R5, 16(R13)
36         MOVW    R6, 20(R13)
37         MOVW    R7, 24(R13)
38         MOVW    R8, 28(R13)
39         MOVW    g, 32(R13)
40         MOVW    R11, 36(R13)
41
42         // Skip floating point registers on GOARM < 6.
43         MOVB    runtime·goarm(SB), R11
44         CMP     $6, R11
45         BLT     skipfpsave
46         MOVD    F8, (40+8*0)(R13)
47         MOVD    F9, (40+8*1)(R13)
48         MOVD    F10, (40+8*2)(R13)
49         MOVD    F11, (40+8*3)(R13)
50         MOVD    F12, (40+8*4)(R13)
51         MOVD    F13, (40+8*5)(R13)
52         MOVD    F14, (40+8*6)(R13)
53         MOVD    F15, (40+8*7)(R13)
54 skipfpsave:
55         // Save argc/argv.
56         MOVW    R0, _rt0_arm_lib_argc<>(SB)
57         MOVW    R1, _rt0_arm_lib_argv<>(SB)
58
59         MOVW    $0, g // Initialize g.
60
61         // Synchronous initialization.
62         CALL    runtime·libpreinit(SB)
63
64         // Create a new thread to do the runtime initialization.
65         MOVW    _cgo_sys_thread_create(SB), R2
66         CMP     $0, R2
67         BEQ     nocgo
68         MOVW    $_rt0_arm_lib_go<>(SB), R0
69         MOVW    $0, R1
70         BL      (R2)
71         B       rr
72 nocgo:
73         MOVW    $0x800000, R0                     // stacksize = 8192KB
74         MOVW    $_rt0_arm_lib_go<>(SB), R1  // fn
75         MOVW    R0, 4(R13)
76         MOVW    R1, 8(R13)
77         BL      runtime·newosproc0(SB)
78 rr:
79         // Restore callee-save registers and return.
80         MOVB    runtime·goarm(SB), R11
81         CMP     $6, R11
82         BLT     skipfprest
83         MOVD    (40+8*0)(R13), F8
84         MOVD    (40+8*1)(R13), F9
85         MOVD    (40+8*2)(R13), F10
86         MOVD    (40+8*3)(R13), F11
87         MOVD    (40+8*4)(R13), F12
88         MOVD    (40+8*5)(R13), F13
89         MOVD    (40+8*6)(R13), F14
90         MOVD    (40+8*7)(R13), F15
91 skipfprest:
92         MOVW    12(R13), R4
93         MOVW    16(R13), R5
94         MOVW    20(R13), R6
95         MOVW    24(R13), R7
96         MOVW    28(R13), R8
97         MOVW    32(R13), g
98         MOVW    36(R13), R11
99         RET
100
101 // _rt0_arm_lib_go initializes the Go runtime.
102 // This is started in a separate thread by _rt0_arm_lib.
103 TEXT _rt0_arm_lib_go<>(SB),NOSPLIT,$8
104         MOVW    _rt0_arm_lib_argc<>(SB), R0
105         MOVW    _rt0_arm_lib_argv<>(SB), R1
106         B       runtime·rt0_go(SB)
107
108 DATA _rt0_arm_lib_argc<>(SB)/4,$0
109 GLOBL _rt0_arm_lib_argc<>(SB),NOPTR,$4
110 DATA _rt0_arm_lib_argv<>(SB)/4,$0
111 GLOBL _rt0_arm_lib_argv<>(SB),NOPTR,$4
112
113 // using NOFRAME means do not save LR on stack.
114 // argc is in R0, argv is in R1.
115 TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
116         MOVW    $0xcafebabe, R12
117
118         // copy arguments forward on an even stack
119         // use R13 instead of SP to avoid linker rewriting the offsets
120         SUB     $64, R13                // plenty of scratch
121         AND     $~7, R13
122         MOVW    R0, 60(R13)             // save argc, argv away
123         MOVW    R1, 64(R13)
124
125         // set up g register
126         // g is R10
127         MOVW    $runtime·g0(SB), g
128         MOVW    $runtime·m0(SB), R8
129
130         // save m->g0 = g0
131         MOVW    g, m_g0(R8)
132         // save g->m = m0
133         MOVW    R8, g_m(g)
134
135         // create istack out of the OS stack
136         // (1MB of system stack is available on iOS and Android)
137         MOVW    $(-64*1024+104)(R13), R0
138         MOVW    R0, g_stackguard0(g)
139         MOVW    R0, g_stackguard1(g)
140         MOVW    R0, (g_stack+stack_lo)(g)
141         MOVW    R13, (g_stack+stack_hi)(g)
142
143         BL      runtime·emptyfunc(SB)  // fault if stack check is wrong
144
145 #ifdef GOOS_openbsd
146         // Save g to TLS so that it is available from signal trampoline.
147         BL      runtime·save_g(SB)
148 #endif
149
150         BL      runtime·_initcgo(SB)   // will clobber R0-R3
151
152         // update stackguard after _cgo_init
153         MOVW    (g_stack+stack_lo)(g), R0
154         ADD     $const__StackGuard, R0
155         MOVW    R0, g_stackguard0(g)
156         MOVW    R0, g_stackguard1(g)
157
158         BL      runtime·check(SB)
159
160         // saved argc, argv
161         MOVW    60(R13), R0
162         MOVW    R0, 4(R13)
163         MOVW    64(R13), R1
164         MOVW    R1, 8(R13)
165         BL      runtime·args(SB)
166         BL      runtime·checkgoarm(SB)
167         BL      runtime·osinit(SB)
168         BL      runtime·schedinit(SB)
169
170         // create a new goroutine to start program
171         SUB     $8, R13
172         MOVW    $runtime·mainPC(SB), R0
173         MOVW    R0, 4(R13)      // arg 1: fn
174         MOVW    $0, R0
175         MOVW    R0, 0(R13)      // dummy LR
176         BL      runtime·newproc(SB)
177         ADD     $8, R13 // pop args and LR
178
179         // start this M
180         BL      runtime·mstart(SB)
181
182         MOVW    $1234, R0
183         MOVW    $1000, R1
184         MOVW    R0, (R1)        // fail hard
185
186 DATA    runtime·mainPC+0(SB)/4,$runtime·main(SB)
187 GLOBL   runtime·mainPC(SB),RODATA,$4
188
189 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
190         // gdb won't skip this breakpoint instruction automatically,
191         // so you must manually "set $pc+=4" to skip it and continue.
192 #ifdef GOOS_plan9
193         WORD    $0xD1200070     // undefined instruction used as armv5 breakpoint in Plan 9
194 #else
195         WORD    $0xe7f001f0     // undefined instruction that gdb understands is a software breakpoint
196 #endif
197         RET
198
199 TEXT runtime·asminit(SB),NOSPLIT,$0-0
200         // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
201         MOVB    runtime·goarm(SB), R11
202         CMP     $5, R11
203         BLE     4(PC)
204         WORD    $0xeef1ba10     // vmrs r11, fpscr
205         BIC     $(1<<24), R11
206         WORD    $0xeee1ba10     // vmsr fpscr, r11
207         RET
208
209 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
210         BL      runtime·mstart0(SB)
211         RET // not reached
212
213 /*
214  *  go-routine
215  */
216
217 // void gogo(Gobuf*)
218 // restore state from Gobuf; longjmp
219 TEXT runtime·gogo(SB),NOSPLIT|NOFRAME,$0-4
220         MOVW    buf+0(FP), R1
221         MOVW    gobuf_g(R1), R0
222         MOVW    0(R0), R2       // make sure g != nil
223         B       gogo<>(SB)
224
225 TEXT gogo<>(SB),NOSPLIT|NOFRAME,$0
226         BL      setg<>(SB)
227         MOVW    gobuf_sp(R1), R13       // restore SP==R13
228         MOVW    gobuf_lr(R1), LR
229         MOVW    gobuf_ret(R1), R0
230         MOVW    gobuf_ctxt(R1), R7
231         MOVW    $0, R11
232         MOVW    R11, gobuf_sp(R1)       // clear to help garbage collector
233         MOVW    R11, gobuf_ret(R1)
234         MOVW    R11, gobuf_lr(R1)
235         MOVW    R11, gobuf_ctxt(R1)
236         MOVW    gobuf_pc(R1), R11
237         CMP     R11, R11 // set condition codes for == test, needed by stack split
238         B       (R11)
239
240 // func mcall(fn func(*g))
241 // Switch to m->g0's stack, call fn(g).
242 // Fn must never return. It should gogo(&g->sched)
243 // to keep running g.
244 TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4
245         // Save caller state in g->sched.
246         MOVW    R13, (g_sched+gobuf_sp)(g)
247         MOVW    LR, (g_sched+gobuf_pc)(g)
248         MOVW    $0, R11
249         MOVW    R11, (g_sched+gobuf_lr)(g)
250
251         // Switch to m->g0 & its stack, call fn.
252         MOVW    g, R1
253         MOVW    g_m(g), R8
254         MOVW    m_g0(R8), R0
255         BL      setg<>(SB)
256         CMP     g, R1
257         B.NE    2(PC)
258         B       runtime·badmcall(SB)
259         MOVW    fn+0(FP), R0
260         MOVW    (g_sched+gobuf_sp)(g), R13
261         SUB     $8, R13
262         MOVW    R1, 4(R13)
263         MOVW    R0, R7
264         MOVW    0(R0), R0
265         BL      (R0)
266         B       runtime·badmcall2(SB)
267         RET
268
269 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
270 // of the G stack. We need to distinguish the routine that
271 // lives at the bottom of the G stack from the one that lives
272 // at the top of the system stack because the one at the top of
273 // the system stack terminates the stack walk (see topofstack()).
274 TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
275         MOVW    $0, R0
276         BL      (R0) // clobber lr to ensure push {lr} is kept
277         RET
278
279 // func systemstack(fn func())
280 TEXT runtime·systemstack(SB),NOSPLIT,$0-4
281         MOVW    fn+0(FP), R0    // R0 = fn
282         MOVW    g_m(g), R1      // R1 = m
283
284         MOVW    m_gsignal(R1), R2       // R2 = gsignal
285         CMP     g, R2
286         B.EQ    noswitch
287
288         MOVW    m_g0(R1), R2    // R2 = g0
289         CMP     g, R2
290         B.EQ    noswitch
291
292         MOVW    m_curg(R1), R3
293         CMP     g, R3
294         B.EQ    switch
295
296         // Bad: g is not gsignal, not g0, not curg. What is it?
297         // Hide call from linker nosplit analysis.
298         MOVW    $runtime·badsystemstack(SB), R0
299         BL      (R0)
300         B       runtime·abort(SB)
301
302 switch:
303         // save our state in g->sched. Pretend to
304         // be systemstack_switch if the G stack is scanned.
305         BL      gosave_systemstack_switch<>(SB)
306
307         // switch to g0
308         MOVW    R0, R5
309         MOVW    R2, R0
310         BL      setg<>(SB)
311         MOVW    R5, R0
312         MOVW    (g_sched+gobuf_sp)(R2), R13
313
314         // call target function
315         MOVW    R0, R7
316         MOVW    0(R0), R0
317         BL      (R0)
318
319         // switch back to g
320         MOVW    g_m(g), R1
321         MOVW    m_curg(R1), R0
322         BL      setg<>(SB)
323         MOVW    (g_sched+gobuf_sp)(g), R13
324         MOVW    $0, R3
325         MOVW    R3, (g_sched+gobuf_sp)(g)
326         RET
327
328 noswitch:
329         // Using a tail call here cleans up tracebacks since we won't stop
330         // at an intermediate systemstack.
331         MOVW    R0, R7
332         MOVW    0(R0), R0
333         MOVW.P  4(R13), R14     // restore LR
334         B       (R0)
335
336 /*
337  * support for morestack
338  */
339
340 // Called during function prolog when more stack is needed.
341 // R3 prolog's LR
342 // using NOFRAME means do not save LR on stack.
343 //
344 // The traceback routines see morestack on a g0 as being
345 // the top of a stack (for example, morestack calling newstack
346 // calling the scheduler calling newm calling gc), so we must
347 // record an argument size. For that purpose, it has no arguments.
348 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
349         // Cannot grow scheduler stack (m->g0).
350         MOVW    g_m(g), R8
351         MOVW    m_g0(R8), R4
352         CMP     g, R4
353         BNE     3(PC)
354         BL      runtime·badmorestackg0(SB)
355         B       runtime·abort(SB)
356
357         // Cannot grow signal stack (m->gsignal).
358         MOVW    m_gsignal(R8), R4
359         CMP     g, R4
360         BNE     3(PC)
361         BL      runtime·badmorestackgsignal(SB)
362         B       runtime·abort(SB)
363
364         // Called from f.
365         // Set g->sched to context in f.
366         MOVW    R13, (g_sched+gobuf_sp)(g)
367         MOVW    LR, (g_sched+gobuf_pc)(g)
368         MOVW    R3, (g_sched+gobuf_lr)(g)
369         MOVW    R7, (g_sched+gobuf_ctxt)(g)
370
371         // Called from f.
372         // Set m->morebuf to f's caller.
373         MOVW    R3, (m_morebuf+gobuf_pc)(R8)    // f's caller's PC
374         MOVW    R13, (m_morebuf+gobuf_sp)(R8)   // f's caller's SP
375         MOVW    g, (m_morebuf+gobuf_g)(R8)
376
377         // Call newstack on m->g0's stack.
378         MOVW    m_g0(R8), R0
379         BL      setg<>(SB)
380         MOVW    (g_sched+gobuf_sp)(g), R13
381         MOVW    $0, R0
382         MOVW.W  R0, -4(R13)     // create a call frame on g0 (saved LR)
383         BL      runtime·newstack(SB)
384
385         // Not reached, but make sure the return PC from the call to newstack
386         // is still in this function, and not the beginning of the next.
387         RET
388
389 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
390         // Force SPWRITE. This function doesn't actually write SP,
391         // but it is called with a special calling convention where
392         // the caller doesn't save LR on stack but passes it as a
393         // register (R3), and the unwinder currently doesn't understand.
394         // Make it SPWRITE to stop unwinding. (See issue 54332)
395         MOVW    R13, R13
396
397         MOVW    $0, R7
398         B runtime·morestack(SB)
399
400 // reflectcall: call a function with the given argument list
401 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
402 // we don't have variable-sized frames, so we use a small number
403 // of constant-sized-frame functions to encode a few bits of size in the pc.
404 // Caution: ugly multiline assembly macros in your future!
405
406 #define DISPATCH(NAME,MAXSIZE)          \
407         CMP     $MAXSIZE, R0;           \
408         B.HI    3(PC);                  \
409         MOVW    $NAME(SB), R1;          \
410         B       (R1)
411
412 TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-28
413         MOVW    frameSize+20(FP), R0
414         DISPATCH(runtime·call16, 16)
415         DISPATCH(runtime·call32, 32)
416         DISPATCH(runtime·call64, 64)
417         DISPATCH(runtime·call128, 128)
418         DISPATCH(runtime·call256, 256)
419         DISPATCH(runtime·call512, 512)
420         DISPATCH(runtime·call1024, 1024)
421         DISPATCH(runtime·call2048, 2048)
422         DISPATCH(runtime·call4096, 4096)
423         DISPATCH(runtime·call8192, 8192)
424         DISPATCH(runtime·call16384, 16384)
425         DISPATCH(runtime·call32768, 32768)
426         DISPATCH(runtime·call65536, 65536)
427         DISPATCH(runtime·call131072, 131072)
428         DISPATCH(runtime·call262144, 262144)
429         DISPATCH(runtime·call524288, 524288)
430         DISPATCH(runtime·call1048576, 1048576)
431         DISPATCH(runtime·call2097152, 2097152)
432         DISPATCH(runtime·call4194304, 4194304)
433         DISPATCH(runtime·call8388608, 8388608)
434         DISPATCH(runtime·call16777216, 16777216)
435         DISPATCH(runtime·call33554432, 33554432)
436         DISPATCH(runtime·call67108864, 67108864)
437         DISPATCH(runtime·call134217728, 134217728)
438         DISPATCH(runtime·call268435456, 268435456)
439         DISPATCH(runtime·call536870912, 536870912)
440         DISPATCH(runtime·call1073741824, 1073741824)
441         MOVW    $runtime·badreflectcall(SB), R1
442         B       (R1)
443
444 #define CALLFN(NAME,MAXSIZE)                    \
445 TEXT NAME(SB), WRAPPER, $MAXSIZE-28;            \
446         NO_LOCAL_POINTERS;                      \
447         /* copy arguments to stack */           \
448         MOVW    stackArgs+8(FP), R0;            \
449         MOVW    stackArgsSize+12(FP), R2;               \
450         ADD     $4, R13, R1;                    \
451         CMP     $0, R2;                         \
452         B.EQ    5(PC);                          \
453         MOVBU.P 1(R0), R5;                      \
454         MOVBU.P R5, 1(R1);                      \
455         SUB     $1, R2, R2;                     \
456         B       -5(PC);                         \
457         /* call function */                     \
458         MOVW    f+4(FP), R7;                    \
459         MOVW    (R7), R0;                       \
460         PCDATA  $PCDATA_StackMapIndex, $0;      \
461         BL      (R0);                           \
462         /* copy return values back */           \
463         MOVW    stackArgsType+0(FP), R4;                \
464         MOVW    stackArgs+8(FP), R0;            \
465         MOVW    stackArgsSize+12(FP), R2;               \
466         MOVW    stackArgsRetOffset+16(FP), R3;          \
467         ADD     $4, R13, R1;                    \
468         ADD     R3, R1;                         \
469         ADD     R3, R0;                         \
470         SUB     R3, R2;                         \
471         BL      callRet<>(SB);                  \
472         RET
473
474 // callRet copies return values back at the end of call*. This is a
475 // separate function so it can allocate stack space for the arguments
476 // to reflectcallmove. It does not follow the Go ABI; it expects its
477 // arguments in registers.
478 TEXT callRet<>(SB), NOSPLIT, $20-0
479         MOVW    R4, 4(R13)
480         MOVW    R0, 8(R13)
481         MOVW    R1, 12(R13)
482         MOVW    R2, 16(R13)
483         MOVW    $0, R7
484         MOVW    R7, 20(R13)
485         BL      runtime·reflectcallmove(SB)
486         RET
487
488 CALLFN(·call16, 16)
489 CALLFN(·call32, 32)
490 CALLFN(·call64, 64)
491 CALLFN(·call128, 128)
492 CALLFN(·call256, 256)
493 CALLFN(·call512, 512)
494 CALLFN(·call1024, 1024)
495 CALLFN(·call2048, 2048)
496 CALLFN(·call4096, 4096)
497 CALLFN(·call8192, 8192)
498 CALLFN(·call16384, 16384)
499 CALLFN(·call32768, 32768)
500 CALLFN(·call65536, 65536)
501 CALLFN(·call131072, 131072)
502 CALLFN(·call262144, 262144)
503 CALLFN(·call524288, 524288)
504 CALLFN(·call1048576, 1048576)
505 CALLFN(·call2097152, 2097152)
506 CALLFN(·call4194304, 4194304)
507 CALLFN(·call8388608, 8388608)
508 CALLFN(·call16777216, 16777216)
509 CALLFN(·call33554432, 33554432)
510 CALLFN(·call67108864, 67108864)
511 CALLFN(·call134217728, 134217728)
512 CALLFN(·call268435456, 268435456)
513 CALLFN(·call536870912, 536870912)
514 CALLFN(·call1073741824, 1073741824)
515
516 // Save state of caller into g->sched,
517 // but using fake PC from systemstack_switch.
518 // Must only be called from functions with no locals ($0)
519 // or else unwinding from systemstack_switch is incorrect.
520 // Smashes R11.
521 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
522         MOVW    $runtime·systemstack_switch(SB), R11
523         ADD     $4, R11 // get past push {lr}
524         MOVW    R11, (g_sched+gobuf_pc)(g)
525         MOVW    R13, (g_sched+gobuf_sp)(g)
526         MOVW    $0, R11
527         MOVW    R11, (g_sched+gobuf_lr)(g)
528         MOVW    R11, (g_sched+gobuf_ret)(g)
529         // Assert ctxt is zero. See func save.
530         MOVW    (g_sched+gobuf_ctxt)(g), R11
531         TST     R11, R11
532         B.EQ    2(PC)
533         BL      runtime·abort(SB)
534         RET
535
536 // func asmcgocall_no_g(fn, arg unsafe.Pointer)
537 // Call fn(arg) aligned appropriately for the gcc ABI.
538 // Called on a system stack, and there may be no g yet (during needm).
539 TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-8
540         MOVW    fn+0(FP), R1
541         MOVW    arg+4(FP), R0
542         MOVW    R13, R2
543         SUB     $32, R13
544         BIC     $0x7, R13       // alignment for gcc ABI
545         MOVW    R2, 8(R13)
546         BL      (R1)
547         MOVW    8(R13), R2
548         MOVW    R2, R13
549         RET
550
551 // func asmcgocall(fn, arg unsafe.Pointer) int32
552 // Call fn(arg) on the scheduler stack,
553 // aligned appropriately for the gcc ABI.
554 // See cgocall.go for more details.
555 TEXT ·asmcgocall(SB),NOSPLIT,$0-12
556         MOVW    fn+0(FP), R1
557         MOVW    arg+4(FP), R0
558
559         MOVW    R13, R2
560         CMP     $0, g
561         BEQ nosave
562         MOVW    g, R4
563
564         // Figure out if we need to switch to m->g0 stack.
565         // We get called to create new OS threads too, and those
566         // come in on the m->g0 stack already. Or we might already
567         // be on the m->gsignal stack.
568         MOVW    g_m(g), R8
569         MOVW    m_gsignal(R8), R3
570         CMP     R3, g
571         BEQ     nosave
572         MOVW    m_g0(R8), R3
573         CMP     R3, g
574         BEQ     nosave
575         BL      gosave_systemstack_switch<>(SB)
576         MOVW    R0, R5
577         MOVW    R3, R0
578         BL      setg<>(SB)
579         MOVW    R5, R0
580         MOVW    (g_sched+gobuf_sp)(g), R13
581
582         // Now on a scheduling stack (a pthread-created stack).
583         SUB     $24, R13
584         BIC     $0x7, R13       // alignment for gcc ABI
585         MOVW    R4, 20(R13) // save old g
586         MOVW    (g_stack+stack_hi)(R4), R4
587         SUB     R2, R4
588         MOVW    R4, 16(R13)     // save depth in stack (can't just save SP, as stack might be copied during a callback)
589         BL      (R1)
590
591         // Restore registers, g, stack pointer.
592         MOVW    R0, R5
593         MOVW    20(R13), R0
594         BL      setg<>(SB)
595         MOVW    (g_stack+stack_hi)(g), R1
596         MOVW    16(R13), R2
597         SUB     R2, R1
598         MOVW    R5, R0
599         MOVW    R1, R13
600
601         MOVW    R0, ret+8(FP)
602         RET
603
604 nosave:
605         // Running on a system stack, perhaps even without a g.
606         // Having no g can happen during thread creation or thread teardown
607         // (see needm/dropm on Solaris, for example).
608         // This code is like the above sequence but without saving/restoring g
609         // and without worrying about the stack moving out from under us
610         // (because we're on a system stack, not a goroutine stack).
611         // The above code could be used directly if already on a system stack,
612         // but then the only path through this code would be a rare case on Solaris.
613         // Using this code for all "already on system stack" calls exercises it more,
614         // which should help keep it correct.
615         SUB     $24, R13
616         BIC     $0x7, R13       // alignment for gcc ABI
617         // save null g in case someone looks during debugging.
618         MOVW    $0, R4
619         MOVW    R4, 20(R13)
620         MOVW    R2, 16(R13)     // Save old stack pointer.
621         BL      (R1)
622         // Restore stack pointer.
623         MOVW    16(R13), R2
624         MOVW    R2, R13
625         MOVW    R0, ret+8(FP)
626         RET
627
628 // cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
629 // See cgocall.go for more details.
630 TEXT    ·cgocallback(SB),NOSPLIT,$12-12
631         NO_LOCAL_POINTERS
632
633         // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
634         // It is used to dropm while thread is exiting.
635         MOVW    fn+0(FP), R1
636         B.NE    loadg
637         // Restore the g from frame.
638         MOVW    frame+4(FP), g
639         B       dropm
640
641 loadg:
642         // Load m and g from thread-local storage.
643 #ifdef GOOS_openbsd
644         BL      runtime·load_g(SB)
645 #else
646         MOVB    runtime·iscgo(SB), R0
647         CMP     $0, R0
648         BL.NE   runtime·load_g(SB)
649 #endif
650
651         // If g is nil, Go did not create the current thread,
652         // or if this thread never called into Go on pthread platforms.
653         // Call needm to obtain one for temporary use.
654         // In this case, we're running on the thread stack, so there's
655         // lots of space, but the linker doesn't know. Hide the call from
656         // the linker analysis by using an indirect call.
657         CMP     $0, g
658         B.EQ    needm
659
660         MOVW    g_m(g), R8
661         MOVW    R8, savedm-4(SP)
662         B       havem
663
664 needm:
665         MOVW    g, savedm-4(SP) // g is zero, so is m.
666         MOVW    $runtime·needAndBindM(SB), R0
667         BL      (R0)
668
669         // Set m->g0->sched.sp = SP, so that if a panic happens
670         // during the function we are about to execute, it will
671         // have a valid SP to run on the g0 stack.
672         // The next few lines (after the havem label)
673         // will save this SP onto the stack and then write
674         // the same SP back to m->sched.sp. That seems redundant,
675         // but if an unrecovered panic happens, unwindm will
676         // restore the g->sched.sp from the stack location
677         // and then systemstack will try to use it. If we don't set it here,
678         // that restored SP will be uninitialized (typically 0) and
679         // will not be usable.
680         MOVW    g_m(g), R8
681         MOVW    m_g0(R8), R3
682         MOVW    R13, (g_sched+gobuf_sp)(R3)
683
684 havem:
685         // Now there's a valid m, and we're running on its m->g0.
686         // Save current m->g0->sched.sp on stack and then set it to SP.
687         // Save current sp in m->g0->sched.sp in preparation for
688         // switch back to m->curg stack.
689         // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-12(SP).
690         MOVW    m_g0(R8), R3
691         MOVW    (g_sched+gobuf_sp)(R3), R4
692         MOVW    R4, savedsp-12(SP)      // must match frame size
693         MOVW    R13, (g_sched+gobuf_sp)(R3)
694
695         // Switch to m->curg stack and call runtime.cgocallbackg.
696         // Because we are taking over the execution of m->curg
697         // but *not* resuming what had been running, we need to
698         // save that information (m->curg->sched) so we can restore it.
699         // We can restore m->curg->sched.sp easily, because calling
700         // runtime.cgocallbackg leaves SP unchanged upon return.
701         // To save m->curg->sched.pc, we push it onto the curg stack and
702         // open a frame the same size as cgocallback's g0 frame.
703         // Once we switch to the curg stack, the pushed PC will appear
704         // to be the return PC of cgocallback, so that the traceback
705         // will seamlessly trace back into the earlier calls.
706         MOVW    m_curg(R8), R0
707         BL      setg<>(SB)
708         MOVW    (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
709         MOVW    (g_sched+gobuf_pc)(g), R5
710         MOVW    R5, -(12+4)(R4) // "saved LR"; must match frame size
711         // Gather our arguments into registers.
712         MOVW    fn+0(FP), R1
713         MOVW    frame+4(FP), R2
714         MOVW    ctxt+8(FP), R3
715         MOVW    $-(12+4)(R4), R13       // switch stack; must match frame size
716         MOVW    R1, 4(R13)
717         MOVW    R2, 8(R13)
718         MOVW    R3, 12(R13)
719         BL      runtime·cgocallbackg(SB)
720
721         // Restore g->sched (== m->curg->sched) from saved values.
722         MOVW    0(R13), R5
723         MOVW    R5, (g_sched+gobuf_pc)(g)
724         MOVW    $(12+4)(R13), R4        // must match frame size
725         MOVW    R4, (g_sched+gobuf_sp)(g)
726
727         // Switch back to m->g0's stack and restore m->g0->sched.sp.
728         // (Unlike m->curg, the g0 goroutine never uses sched.pc,
729         // so we do not have to restore it.)
730         MOVW    g_m(g), R8
731         MOVW    m_g0(R8), R0
732         BL      setg<>(SB)
733         MOVW    (g_sched+gobuf_sp)(g), R13
734         MOVW    savedsp-12(SP), R4      // must match frame size
735         MOVW    R4, (g_sched+gobuf_sp)(g)
736
737         // If the m on entry was nil, we called needm above to borrow an m,
738         // 1. for the duration of the call on non-pthread platforms,
739         // 2. or the duration of the C thread alive on pthread platforms.
740         // If the m on entry wasn't nil,
741         // 1. the thread might be a Go thread,
742         // 2. or it's wasn't the first call from a C thread on pthread platforms,
743         //    since the we skip dropm to resue the m in the first call.
744         MOVW    savedm-4(SP), R6
745         CMP     $0, R6
746         B.NE    done
747
748         // Skip dropm to reuse it in the next call, when a pthread key has been created.
749         MOVW    _cgo_pthread_key_created(SB), R6
750         // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
751         CMP     $0, R6
752         B.EQ    dropm
753         MOVW    (R6), R6
754         CMP     $0, R6
755         B.NE    done
756
757 dropm:
758         MOVW    $runtime·dropm(SB), R0
759         BL      (R0)
760
761 done:
762         // Done!
763         RET
764
765 // void setg(G*); set g. for use by needm.
766 TEXT runtime·setg(SB),NOSPLIT|NOFRAME,$0-4
767         MOVW    gg+0(FP), R0
768         B       setg<>(SB)
769
770 TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0
771         MOVW    R0, g
772
773         // Save g to thread-local storage.
774 #ifdef GOOS_windows
775         B       runtime·save_g(SB)
776 #else
777 #ifdef GOOS_openbsd
778         B       runtime·save_g(SB)
779 #else
780         MOVB    runtime·iscgo(SB), R0
781         CMP     $0, R0
782         B.EQ    2(PC)
783         B       runtime·save_g(SB)
784
785         MOVW    g, R0
786         RET
787 #endif
788 #endif
789
790 TEXT runtime·emptyfunc(SB),0,$0-0
791         RET
792
793 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
794         MOVW    $0, R0
795         MOVW    (R0), R1
796
797 // armPublicationBarrier is a native store/store barrier for ARMv7+.
798 // On earlier ARM revisions, armPublicationBarrier is a no-op.
799 // This will not work on SMP ARMv6 machines, if any are in use.
800 // To implement publicationBarrier in sys_$GOOS_arm.s using the native
801 // instructions, use:
802 //
803 //      TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
804 //              B       runtime·armPublicationBarrier(SB)
805 //
806 TEXT runtime·armPublicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
807         MOVB    runtime·goarm(SB), R11
808         CMP     $7, R11
809         BLT     2(PC)
810         DMB     MB_ST
811         RET
812
813 // AES hashing not implemented for ARM
814 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16
815         JMP     runtime·memhashFallback(SB)
816 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12
817         JMP     runtime·strhashFallback(SB)
818 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12
819         JMP     runtime·memhash32Fallback(SB)
820 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12
821         JMP     runtime·memhash64Fallback(SB)
822
823 TEXT runtime·return0(SB),NOSPLIT,$0
824         MOVW    $0, R0
825         RET
826
827 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0
828         MOVW    cycles+0(FP), R1
829         MOVW    $0, R0
830 yieldloop:
831         WORD    $0xe320f001     // YIELD (NOP pre-ARMv6K)
832         CMP     R0, R1
833         B.NE    2(PC)
834         RET
835         SUB     $1, R1
836         B yieldloop
837
838 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
839 // Must obey the gcc calling convention.
840 TEXT _cgo_topofstack(SB),NOSPLIT,$8
841         // R11 and g register are clobbered by load_g. They are
842         // callee-save in the gcc calling convention, so save them here.
843         MOVW    R11, saveR11-4(SP)
844         MOVW    g, saveG-8(SP)
845
846         BL      runtime·load_g(SB)
847         MOVW    g_m(g), R0
848         MOVW    m_curg(R0), R0
849         MOVW    (g_stack+stack_hi)(R0), R0
850
851         MOVW    saveG-8(SP), g
852         MOVW    saveR11-4(SP), R11
853         RET
854
855 // The top-most function running on a goroutine
856 // returns to goexit+PCQuantum.
857 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
858         MOVW    R0, R0  // NOP
859         BL      runtime·goexit1(SB)    // does not return
860         // traceback from goexit1 must hit code range of goexit
861         MOVW    R0, R0  // NOP
862
863 // x -> x/1000000, x%1000000, called from Go with args, results on stack.
864 TEXT runtime·usplit(SB),NOSPLIT,$0-12
865         MOVW    x+0(FP), R0
866         CALL    runtime·usplitR0(SB)
867         MOVW    R0, q+4(FP)
868         MOVW    R1, r+8(FP)
869         RET
870
871 // R0, R1 = R0/1000000, R0%1000000
872 TEXT runtime·usplitR0(SB),NOSPLIT,$0
873         // magic multiply to avoid software divide without available m.
874         // see output of go tool compile -S for x/1000000.
875         MOVW    R0, R3
876         MOVW    $1125899907, R1
877         MULLU   R1, R0, (R0, R1)
878         MOVW    R0>>18, R0
879         MOVW    $1000000, R1
880         MULU    R0, R1
881         SUB     R1, R3, R1
882         RET
883
884 // This is called from .init_array and follows the platform, not Go, ABI.
885 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
886         MOVW    R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
887         MOVW    R11, saver11-8(SP) // Likewise, R11 is the temp register, but callee-save in C ABI
888         MOVW    runtime·lastmoduledatap(SB), R1
889         MOVW    R0, moduledata_next(R1)
890         MOVW    R0, runtime·lastmoduledatap(SB)
891         MOVW    saver11-8(SP), R11
892         MOVW    saver9-4(SP), R9
893         RET
894
895 TEXT ·checkASM(SB),NOSPLIT,$0-1
896         MOVW    $1, R3
897         MOVB    R3, ret+0(FP)
898         RET
899
900 // gcWriteBarrier informs the GC about heap pointer writes.
901 //
902 // gcWriteBarrier does NOT follow the Go ABI. It accepts the
903 // number of bytes of buffer needed in R8, and returns a pointer
904 // to the buffer space in R8.
905 // It clobbers condition codes.
906 // It does not clobber any other general-purpose registers,
907 // but may clobber others (e.g., floating point registers).
908 // The act of CALLing gcWriteBarrier will clobber R14 (LR).
909 TEXT gcWriteBarrier<>(SB),NOSPLIT|NOFRAME,$0
910         // Save the registers clobbered by the fast path.
911         MOVM.DB.W       [R0,R1], (R13)
912 retry:
913         MOVW    g_m(g), R0
914         MOVW    m_p(R0), R0
915         MOVW    (p_wbBuf+wbBuf_next)(R0), R1
916         MOVW    (p_wbBuf+wbBuf_end)(R0), R11
917         // Increment wbBuf.next position.
918         ADD     R8, R1
919         // Is the buffer full?
920         CMP     R11, R1
921         BHI     flush
922         // Commit to the larger buffer.
923         MOVW    R1, (p_wbBuf+wbBuf_next)(R0)
924         // Make return value (the original next position)
925         SUB     R8, R1, R8
926         // Restore registers.
927         MOVM.IA.W       (R13), [R0,R1]
928         RET
929
930 flush:
931         // Save all general purpose registers since these could be
932         // clobbered by wbBufFlush and were not saved by the caller.
933         //
934         // R0 and R1 were saved at entry.
935         // R10 is g, so preserved.
936         // R11 is linker temp, so no need to save.
937         // R13 is stack pointer.
938         // R15 is PC.
939         MOVM.DB.W       [R2-R9,R12], (R13)
940         // Save R14 (LR) because the fast path above doesn't save it,
941         // but needs it to RET.
942         MOVM.DB.W       [R14], (R13)
943
944         CALL    runtime·wbBufFlush(SB)
945
946         MOVM.IA.W       (R13), [R14]
947         MOVM.IA.W       (R13), [R2-R9,R12]
948         JMP     retry
949
950 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
951         MOVW    $4, R8
952         JMP     gcWriteBarrier<>(SB)
953 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
954         MOVW    $8, R8
955         JMP     gcWriteBarrier<>(SB)
956 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
957         MOVW    $12, R8
958         JMP     gcWriteBarrier<>(SB)
959 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
960         MOVW    $16, R8
961         JMP     gcWriteBarrier<>(SB)
962 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
963         MOVW    $20, R8
964         JMP     gcWriteBarrier<>(SB)
965 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
966         MOVW    $24, R8
967         JMP     gcWriteBarrier<>(SB)
968 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
969         MOVW    $28, R8
970         JMP     gcWriteBarrier<>(SB)
971 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
972         MOVW    $32, R8
973         JMP     gcWriteBarrier<>(SB)
974
975 // Note: these functions use a special calling convention to save generated code space.
976 // Arguments are passed in registers, but the space for those arguments are allocated
977 // in the caller's stack frame. These stubs write the args into that stack space and
978 // then tail call to the corresponding runtime handler.
979 // The tail call makes these stubs disappear in backtraces.
980 TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
981         MOVW    R0, x+0(FP)
982         MOVW    R1, y+4(FP)
983         JMP     runtime·goPanicIndex(SB)
984 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
985         MOVW    R0, x+0(FP)
986         MOVW    R1, y+4(FP)
987         JMP     runtime·goPanicIndexU(SB)
988 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
989         MOVW    R1, x+0(FP)
990         MOVW    R2, y+4(FP)
991         JMP     runtime·goPanicSliceAlen(SB)
992 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
993         MOVW    R1, x+0(FP)
994         MOVW    R2, y+4(FP)
995         JMP     runtime·goPanicSliceAlenU(SB)
996 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
997         MOVW    R1, x+0(FP)
998         MOVW    R2, y+4(FP)
999         JMP     runtime·goPanicSliceAcap(SB)
1000 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
1001         MOVW    R1, x+0(FP)
1002         MOVW    R2, y+4(FP)
1003         JMP     runtime·goPanicSliceAcapU(SB)
1004 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
1005         MOVW    R0, x+0(FP)
1006         MOVW    R1, y+4(FP)
1007         JMP     runtime·goPanicSliceB(SB)
1008 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
1009         MOVW    R0, x+0(FP)
1010         MOVW    R1, y+4(FP)
1011         JMP     runtime·goPanicSliceBU(SB)
1012 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
1013         MOVW    R2, x+0(FP)
1014         MOVW    R3, y+4(FP)
1015         JMP     runtime·goPanicSlice3Alen(SB)
1016 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
1017         MOVW    R2, x+0(FP)
1018         MOVW    R3, y+4(FP)
1019         JMP     runtime·goPanicSlice3AlenU(SB)
1020 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
1021         MOVW    R2, x+0(FP)
1022         MOVW    R3, y+4(FP)
1023         JMP     runtime·goPanicSlice3Acap(SB)
1024 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
1025         MOVW    R2, x+0(FP)
1026         MOVW    R3, y+4(FP)
1027         JMP     runtime·goPanicSlice3AcapU(SB)
1028 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
1029         MOVW    R1, x+0(FP)
1030         MOVW    R2, y+4(FP)
1031         JMP     runtime·goPanicSlice3B(SB)
1032 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
1033         MOVW    R1, x+0(FP)
1034         MOVW    R2, y+4(FP)
1035         JMP     runtime·goPanicSlice3BU(SB)
1036 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
1037         MOVW    R0, x+0(FP)
1038         MOVW    R1, y+4(FP)
1039         JMP     runtime·goPanicSlice3C(SB)
1040 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
1041         MOVW    R0, x+0(FP)
1042         MOVW    R1, y+4(FP)
1043         JMP     runtime·goPanicSlice3CU(SB)
1044 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8
1045         MOVW    R2, x+0(FP)
1046         MOVW    R3, y+4(FP)
1047         JMP     runtime·goPanicSliceConvert(SB)
1048
1049 // Extended versions for 64-bit indexes.
1050 TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
1051         MOVW    R4, hi+0(FP)
1052         MOVW    R0, lo+4(FP)
1053         MOVW    R1, y+8(FP)
1054         JMP     runtime·goPanicExtendIndex(SB)
1055 TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
1056         MOVW    R4, hi+0(FP)
1057         MOVW    R0, lo+4(FP)
1058         MOVW    R1, y+8(FP)
1059         JMP     runtime·goPanicExtendIndexU(SB)
1060 TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
1061         MOVW    R4, hi+0(FP)
1062         MOVW    R1, lo+4(FP)
1063         MOVW    R2, y+8(FP)
1064         JMP     runtime·goPanicExtendSliceAlen(SB)
1065 TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
1066         MOVW    R4, hi+0(FP)
1067         MOVW    R1, lo+4(FP)
1068         MOVW    R2, y+8(FP)
1069         JMP     runtime·goPanicExtendSliceAlenU(SB)
1070 TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
1071         MOVW    R4, hi+0(FP)
1072         MOVW    R1, lo+4(FP)
1073         MOVW    R2, y+8(FP)
1074         JMP     runtime·goPanicExtendSliceAcap(SB)
1075 TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
1076         MOVW    R4, hi+0(FP)
1077         MOVW    R1, lo+4(FP)
1078         MOVW    R2, y+8(FP)
1079         JMP     runtime·goPanicExtendSliceAcapU(SB)
1080 TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
1081         MOVW    R4, hi+0(FP)
1082         MOVW    R0, lo+4(FP)
1083         MOVW    R1, y+8(FP)
1084         JMP     runtime·goPanicExtendSliceB(SB)
1085 TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
1086         MOVW    R4, hi+0(FP)
1087         MOVW    R0, lo+4(FP)
1088         MOVW    R1, y+8(FP)
1089         JMP     runtime·goPanicExtendSliceBU(SB)
1090 TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
1091         MOVW    R4, hi+0(FP)
1092         MOVW    R2, lo+4(FP)
1093         MOVW    R3, y+8(FP)
1094         JMP     runtime·goPanicExtendSlice3Alen(SB)
1095 TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
1096         MOVW    R4, hi+0(FP)
1097         MOVW    R2, lo+4(FP)
1098         MOVW    R3, y+8(FP)
1099         JMP     runtime·goPanicExtendSlice3AlenU(SB)
1100 TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
1101         MOVW    R4, hi+0(FP)
1102         MOVW    R2, lo+4(FP)
1103         MOVW    R3, y+8(FP)
1104         JMP     runtime·goPanicExtendSlice3Acap(SB)
1105 TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
1106         MOVW    R4, hi+0(FP)
1107         MOVW    R2, lo+4(FP)
1108         MOVW    R3, y+8(FP)
1109         JMP     runtime·goPanicExtendSlice3AcapU(SB)
1110 TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
1111         MOVW    R4, hi+0(FP)
1112         MOVW    R1, lo+4(FP)
1113         MOVW    R2, y+8(FP)
1114         JMP     runtime·goPanicExtendSlice3B(SB)
1115 TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
1116         MOVW    R4, hi+0(FP)
1117         MOVW    R1, lo+4(FP)
1118         MOVW    R2, y+8(FP)
1119         JMP     runtime·goPanicExtendSlice3BU(SB)
1120 TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
1121         MOVW    R4, hi+0(FP)
1122         MOVW    R0, lo+4(FP)
1123         MOVW    R1, y+8(FP)
1124         JMP     runtime·goPanicExtendSlice3C(SB)
1125 TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
1126         MOVW    R4, hi+0(FP)
1127         MOVW    R0, lo+4(FP)
1128         MOVW    R1, y+8(FP)
1129         JMP     runtime·goPanicExtendSlice3CU(SB)