]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_arm.s
Revert "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         // Load m and g from thread-local storage.
634 #ifdef GOOS_openbsd
635         BL      runtime·load_g(SB)
636 #else
637         MOVB    runtime·iscgo(SB), R0
638         CMP     $0, R0
639         BL.NE   runtime·load_g(SB)
640 #endif
641
642         // If g is nil, Go did not create the current thread.
643         // Call needm to obtain one for temporary use.
644         // In this case, we're running on the thread stack, so there's
645         // lots of space, but the linker doesn't know. Hide the call from
646         // the linker analysis by using an indirect call.
647         CMP     $0, g
648         B.EQ    needm
649
650         MOVW    g_m(g), R8
651         MOVW    R8, savedm-4(SP)
652         B       havem
653
654 needm:
655         MOVW    g, savedm-4(SP) // g is zero, so is m.
656         MOVW    $runtime·needm(SB), R0
657         BL      (R0)
658
659         // Set m->g0->sched.sp = SP, so that if a panic happens
660         // during the function we are about to execute, it will
661         // have a valid SP to run on the g0 stack.
662         // The next few lines (after the havem label)
663         // will save this SP onto the stack and then write
664         // the same SP back to m->sched.sp. That seems redundant,
665         // but if an unrecovered panic happens, unwindm will
666         // restore the g->sched.sp from the stack location
667         // and then systemstack will try to use it. If we don't set it here,
668         // that restored SP will be uninitialized (typically 0) and
669         // will not be usable.
670         MOVW    g_m(g), R8
671         MOVW    m_g0(R8), R3
672         MOVW    R13, (g_sched+gobuf_sp)(R3)
673
674 havem:
675         // Now there's a valid m, and we're running on its m->g0.
676         // Save current m->g0->sched.sp on stack and then set it to SP.
677         // Save current sp in m->g0->sched.sp in preparation for
678         // switch back to m->curg stack.
679         // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-12(SP).
680         MOVW    m_g0(R8), R3
681         MOVW    (g_sched+gobuf_sp)(R3), R4
682         MOVW    R4, savedsp-12(SP)      // must match frame size
683         MOVW    R13, (g_sched+gobuf_sp)(R3)
684
685         // Switch to m->curg stack and call runtime.cgocallbackg.
686         // Because we are taking over the execution of m->curg
687         // but *not* resuming what had been running, we need to
688         // save that information (m->curg->sched) so we can restore it.
689         // We can restore m->curg->sched.sp easily, because calling
690         // runtime.cgocallbackg leaves SP unchanged upon return.
691         // To save m->curg->sched.pc, we push it onto the curg stack and
692         // open a frame the same size as cgocallback's g0 frame.
693         // Once we switch to the curg stack, the pushed PC will appear
694         // to be the return PC of cgocallback, so that the traceback
695         // will seamlessly trace back into the earlier calls.
696         MOVW    m_curg(R8), R0
697         BL      setg<>(SB)
698         MOVW    (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
699         MOVW    (g_sched+gobuf_pc)(g), R5
700         MOVW    R5, -(12+4)(R4) // "saved LR"; must match frame size
701         // Gather our arguments into registers.
702         MOVW    fn+0(FP), R1
703         MOVW    frame+4(FP), R2
704         MOVW    ctxt+8(FP), R3
705         MOVW    $-(12+4)(R4), R13       // switch stack; must match frame size
706         MOVW    R1, 4(R13)
707         MOVW    R2, 8(R13)
708         MOVW    R3, 12(R13)
709         BL      runtime·cgocallbackg(SB)
710
711         // Restore g->sched (== m->curg->sched) from saved values.
712         MOVW    0(R13), R5
713         MOVW    R5, (g_sched+gobuf_pc)(g)
714         MOVW    $(12+4)(R13), R4        // must match frame size
715         MOVW    R4, (g_sched+gobuf_sp)(g)
716
717         // Switch back to m->g0's stack and restore m->g0->sched.sp.
718         // (Unlike m->curg, the g0 goroutine never uses sched.pc,
719         // so we do not have to restore it.)
720         MOVW    g_m(g), R8
721         MOVW    m_g0(R8), R0
722         BL      setg<>(SB)
723         MOVW    (g_sched+gobuf_sp)(g), R13
724         MOVW    savedsp-12(SP), R4      // must match frame size
725         MOVW    R4, (g_sched+gobuf_sp)(g)
726
727         // If the m on entry was nil, we called needm above to borrow an m
728         // for the duration of the call. Since the call is over, return it with dropm.
729         MOVW    savedm-4(SP), R6
730         CMP     $0, R6
731         B.NE    3(PC)
732         MOVW    $runtime·dropm(SB), R0
733         BL      (R0)
734
735         // Done!
736         RET
737
738 // void setg(G*); set g. for use by needm.
739 TEXT runtime·setg(SB),NOSPLIT|NOFRAME,$0-4
740         MOVW    gg+0(FP), R0
741         B       setg<>(SB)
742
743 TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0
744         MOVW    R0, g
745
746         // Save g to thread-local storage.
747 #ifdef GOOS_windows
748         B       runtime·save_g(SB)
749 #else
750 #ifdef GOOS_openbsd
751         B       runtime·save_g(SB)
752 #else
753         MOVB    runtime·iscgo(SB), R0
754         CMP     $0, R0
755         B.EQ    2(PC)
756         B       runtime·save_g(SB)
757
758         MOVW    g, R0
759         RET
760 #endif
761 #endif
762
763 TEXT runtime·emptyfunc(SB),0,$0-0
764         RET
765
766 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
767         MOVW    $0, R0
768         MOVW    (R0), R1
769
770 // armPublicationBarrier is a native store/store barrier for ARMv7+.
771 // On earlier ARM revisions, armPublicationBarrier is a no-op.
772 // This will not work on SMP ARMv6 machines, if any are in use.
773 // To implement publicationBarrier in sys_$GOOS_arm.s using the native
774 // instructions, use:
775 //
776 //      TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
777 //              B       runtime·armPublicationBarrier(SB)
778 //
779 TEXT runtime·armPublicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
780         MOVB    runtime·goarm(SB), R11
781         CMP     $7, R11
782         BLT     2(PC)
783         DMB     MB_ST
784         RET
785
786 // AES hashing not implemented for ARM
787 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16
788         JMP     runtime·memhashFallback(SB)
789 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12
790         JMP     runtime·strhashFallback(SB)
791 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12
792         JMP     runtime·memhash32Fallback(SB)
793 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12
794         JMP     runtime·memhash64Fallback(SB)
795
796 TEXT runtime·return0(SB),NOSPLIT,$0
797         MOVW    $0, R0
798         RET
799
800 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0
801         MOVW    cycles+0(FP), R1
802         MOVW    $0, R0
803 yieldloop:
804         WORD    $0xe320f001     // YIELD (NOP pre-ARMv6K)
805         CMP     R0, R1
806         B.NE    2(PC)
807         RET
808         SUB     $1, R1
809         B yieldloop
810
811 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
812 // Must obey the gcc calling convention.
813 TEXT _cgo_topofstack(SB),NOSPLIT,$8
814         // R11 and g register are clobbered by load_g. They are
815         // callee-save in the gcc calling convention, so save them here.
816         MOVW    R11, saveR11-4(SP)
817         MOVW    g, saveG-8(SP)
818
819         BL      runtime·load_g(SB)
820         MOVW    g_m(g), R0
821         MOVW    m_curg(R0), R0
822         MOVW    (g_stack+stack_hi)(R0), R0
823
824         MOVW    saveG-8(SP), g
825         MOVW    saveR11-4(SP), R11
826         RET
827
828 // The top-most function running on a goroutine
829 // returns to goexit+PCQuantum.
830 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
831         MOVW    R0, R0  // NOP
832         BL      runtime·goexit1(SB)    // does not return
833         // traceback from goexit1 must hit code range of goexit
834         MOVW    R0, R0  // NOP
835
836 // x -> x/1000000, x%1000000, called from Go with args, results on stack.
837 TEXT runtime·usplit(SB),NOSPLIT,$0-12
838         MOVW    x+0(FP), R0
839         CALL    runtime·usplitR0(SB)
840         MOVW    R0, q+4(FP)
841         MOVW    R1, r+8(FP)
842         RET
843
844 // R0, R1 = R0/1000000, R0%1000000
845 TEXT runtime·usplitR0(SB),NOSPLIT,$0
846         // magic multiply to avoid software divide without available m.
847         // see output of go tool compile -S for x/1000000.
848         MOVW    R0, R3
849         MOVW    $1125899907, R1
850         MULLU   R1, R0, (R0, R1)
851         MOVW    R0>>18, R0
852         MOVW    $1000000, R1
853         MULU    R0, R1
854         SUB     R1, R3, R1
855         RET
856
857 // This is called from .init_array and follows the platform, not Go, ABI.
858 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
859         MOVW    R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
860         MOVW    R11, saver11-8(SP) // Likewise, R11 is the temp register, but callee-save in C ABI
861         MOVW    runtime·lastmoduledatap(SB), R1
862         MOVW    R0, moduledata_next(R1)
863         MOVW    R0, runtime·lastmoduledatap(SB)
864         MOVW    saver11-8(SP), R11
865         MOVW    saver9-4(SP), R9
866         RET
867
868 TEXT ·checkASM(SB),NOSPLIT,$0-1
869         MOVW    $1, R3
870         MOVB    R3, ret+0(FP)
871         RET
872
873 // gcWriteBarrier informs the GC about heap pointer writes.
874 //
875 // gcWriteBarrier does NOT follow the Go ABI. It accepts the
876 // number of bytes of buffer needed in R8, and returns a pointer
877 // to the buffer space in R8.
878 // It clobbers condition codes.
879 // It does not clobber any other general-purpose registers,
880 // but may clobber others (e.g., floating point registers).
881 // The act of CALLing gcWriteBarrier will clobber R14 (LR).
882 TEXT gcWriteBarrier<>(SB),NOSPLIT|NOFRAME,$0
883         // Save the registers clobbered by the fast path.
884         MOVM.DB.W       [R0,R1], (R13)
885 retry:
886         MOVW    g_m(g), R0
887         MOVW    m_p(R0), R0
888         MOVW    (p_wbBuf+wbBuf_next)(R0), R1
889         MOVW    (p_wbBuf+wbBuf_end)(R0), R11
890         // Increment wbBuf.next position.
891         ADD     R8, R1
892         // Is the buffer full?
893         CMP     R11, R1
894         BHI     flush
895         // Commit to the larger buffer.
896         MOVW    R1, (p_wbBuf+wbBuf_next)(R0)
897         // Make return value (the original next position)
898         SUB     R8, R1, R8
899         // Restore registers.
900         MOVM.IA.W       (R13), [R0,R1]
901         RET
902
903 flush:
904         // Save all general purpose registers since these could be
905         // clobbered by wbBufFlush and were not saved by the caller.
906         //
907         // R0 and R1 were saved at entry.
908         // R10 is g, so preserved.
909         // R11 is linker temp, so no need to save.
910         // R13 is stack pointer.
911         // R15 is PC.
912         MOVM.DB.W       [R2-R9,R12], (R13)
913         // Save R14 (LR) because the fast path above doesn't save it,
914         // but needs it to RET.
915         MOVM.DB.W       [R14], (R13)
916
917         CALL    runtime·wbBufFlush(SB)
918
919         MOVM.IA.W       (R13), [R14]
920         MOVM.IA.W       (R13), [R2-R9,R12]
921         JMP     retry
922
923 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
924         MOVW    $4, R8
925         JMP     gcWriteBarrier<>(SB)
926 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
927         MOVW    $8, R8
928         JMP     gcWriteBarrier<>(SB)
929 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
930         MOVW    $12, R8
931         JMP     gcWriteBarrier<>(SB)
932 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
933         MOVW    $16, R8
934         JMP     gcWriteBarrier<>(SB)
935 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
936         MOVW    $20, R8
937         JMP     gcWriteBarrier<>(SB)
938 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
939         MOVW    $24, R8
940         JMP     gcWriteBarrier<>(SB)
941 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
942         MOVW    $28, R8
943         JMP     gcWriteBarrier<>(SB)
944 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
945         MOVW    $32, R8
946         JMP     gcWriteBarrier<>(SB)
947
948 // Note: these functions use a special calling convention to save generated code space.
949 // Arguments are passed in registers, but the space for those arguments are allocated
950 // in the caller's stack frame. These stubs write the args into that stack space and
951 // then tail call to the corresponding runtime handler.
952 // The tail call makes these stubs disappear in backtraces.
953 TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
954         MOVW    R0, x+0(FP)
955         MOVW    R1, y+4(FP)
956         JMP     runtime·goPanicIndex(SB)
957 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
958         MOVW    R0, x+0(FP)
959         MOVW    R1, y+4(FP)
960         JMP     runtime·goPanicIndexU(SB)
961 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
962         MOVW    R1, x+0(FP)
963         MOVW    R2, y+4(FP)
964         JMP     runtime·goPanicSliceAlen(SB)
965 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
966         MOVW    R1, x+0(FP)
967         MOVW    R2, y+4(FP)
968         JMP     runtime·goPanicSliceAlenU(SB)
969 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
970         MOVW    R1, x+0(FP)
971         MOVW    R2, y+4(FP)
972         JMP     runtime·goPanicSliceAcap(SB)
973 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
974         MOVW    R1, x+0(FP)
975         MOVW    R2, y+4(FP)
976         JMP     runtime·goPanicSliceAcapU(SB)
977 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
978         MOVW    R0, x+0(FP)
979         MOVW    R1, y+4(FP)
980         JMP     runtime·goPanicSliceB(SB)
981 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
982         MOVW    R0, x+0(FP)
983         MOVW    R1, y+4(FP)
984         JMP     runtime·goPanicSliceBU(SB)
985 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
986         MOVW    R2, x+0(FP)
987         MOVW    R3, y+4(FP)
988         JMP     runtime·goPanicSlice3Alen(SB)
989 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
990         MOVW    R2, x+0(FP)
991         MOVW    R3, y+4(FP)
992         JMP     runtime·goPanicSlice3AlenU(SB)
993 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
994         MOVW    R2, x+0(FP)
995         MOVW    R3, y+4(FP)
996         JMP     runtime·goPanicSlice3Acap(SB)
997 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
998         MOVW    R2, x+0(FP)
999         MOVW    R3, y+4(FP)
1000         JMP     runtime·goPanicSlice3AcapU(SB)
1001 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
1002         MOVW    R1, x+0(FP)
1003         MOVW    R2, y+4(FP)
1004         JMP     runtime·goPanicSlice3B(SB)
1005 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
1006         MOVW    R1, x+0(FP)
1007         MOVW    R2, y+4(FP)
1008         JMP     runtime·goPanicSlice3BU(SB)
1009 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
1010         MOVW    R0, x+0(FP)
1011         MOVW    R1, y+4(FP)
1012         JMP     runtime·goPanicSlice3C(SB)
1013 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
1014         MOVW    R0, x+0(FP)
1015         MOVW    R1, y+4(FP)
1016         JMP     runtime·goPanicSlice3CU(SB)
1017 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8
1018         MOVW    R2, x+0(FP)
1019         MOVW    R3, y+4(FP)
1020         JMP     runtime·goPanicSliceConvert(SB)
1021
1022 // Extended versions for 64-bit indexes.
1023 TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
1024         MOVW    R4, hi+0(FP)
1025         MOVW    R0, lo+4(FP)
1026         MOVW    R1, y+8(FP)
1027         JMP     runtime·goPanicExtendIndex(SB)
1028 TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
1029         MOVW    R4, hi+0(FP)
1030         MOVW    R0, lo+4(FP)
1031         MOVW    R1, y+8(FP)
1032         JMP     runtime·goPanicExtendIndexU(SB)
1033 TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
1034         MOVW    R4, hi+0(FP)
1035         MOVW    R1, lo+4(FP)
1036         MOVW    R2, y+8(FP)
1037         JMP     runtime·goPanicExtendSliceAlen(SB)
1038 TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
1039         MOVW    R4, hi+0(FP)
1040         MOVW    R1, lo+4(FP)
1041         MOVW    R2, y+8(FP)
1042         JMP     runtime·goPanicExtendSliceAlenU(SB)
1043 TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
1044         MOVW    R4, hi+0(FP)
1045         MOVW    R1, lo+4(FP)
1046         MOVW    R2, y+8(FP)
1047         JMP     runtime·goPanicExtendSliceAcap(SB)
1048 TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
1049         MOVW    R4, hi+0(FP)
1050         MOVW    R1, lo+4(FP)
1051         MOVW    R2, y+8(FP)
1052         JMP     runtime·goPanicExtendSliceAcapU(SB)
1053 TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
1054         MOVW    R4, hi+0(FP)
1055         MOVW    R0, lo+4(FP)
1056         MOVW    R1, y+8(FP)
1057         JMP     runtime·goPanicExtendSliceB(SB)
1058 TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
1059         MOVW    R4, hi+0(FP)
1060         MOVW    R0, lo+4(FP)
1061         MOVW    R1, y+8(FP)
1062         JMP     runtime·goPanicExtendSliceBU(SB)
1063 TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
1064         MOVW    R4, hi+0(FP)
1065         MOVW    R2, lo+4(FP)
1066         MOVW    R3, y+8(FP)
1067         JMP     runtime·goPanicExtendSlice3Alen(SB)
1068 TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
1069         MOVW    R4, hi+0(FP)
1070         MOVW    R2, lo+4(FP)
1071         MOVW    R3, y+8(FP)
1072         JMP     runtime·goPanicExtendSlice3AlenU(SB)
1073 TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
1074         MOVW    R4, hi+0(FP)
1075         MOVW    R2, lo+4(FP)
1076         MOVW    R3, y+8(FP)
1077         JMP     runtime·goPanicExtendSlice3Acap(SB)
1078 TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
1079         MOVW    R4, hi+0(FP)
1080         MOVW    R2, lo+4(FP)
1081         MOVW    R3, y+8(FP)
1082         JMP     runtime·goPanicExtendSlice3AcapU(SB)
1083 TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
1084         MOVW    R4, hi+0(FP)
1085         MOVW    R1, lo+4(FP)
1086         MOVW    R2, y+8(FP)
1087         JMP     runtime·goPanicExtendSlice3B(SB)
1088 TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
1089         MOVW    R4, hi+0(FP)
1090         MOVW    R1, lo+4(FP)
1091         MOVW    R2, y+8(FP)
1092         JMP     runtime·goPanicExtendSlice3BU(SB)
1093 TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
1094         MOVW    R4, hi+0(FP)
1095         MOVW    R0, lo+4(FP)
1096         MOVW    R1, y+8(FP)
1097         JMP     runtime·goPanicExtendSlice3C(SB)
1098 TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
1099         MOVW    R4, hi+0(FP)
1100         MOVW    R0, lo+4(FP)
1101         MOVW    R1, y+8(FP)
1102         JMP     runtime·goPanicExtendSlice3CU(SB)