]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_arm.s
[dev.power64] all: merge default (dd5014ed9b01) into dev.power64
[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 "zasm_GOOS_GOARCH.h"
6 #include "funcdata.h"
7 #include "textflag.h"
8
9 // using frame size $-4 means do not save LR on stack.
10 TEXT runtime·rt0_go(SB),NOSPLIT,$-4
11         MOVW    $0xcafebabe, R12
12
13         // copy arguments forward on an even stack
14         // use R13 instead of SP to avoid linker rewriting the offsets
15         MOVW    0(R13), R0              // argc
16         MOVW    4(R13), R1              // argv
17         SUB     $64, R13                // plenty of scratch
18         AND     $~7, R13
19         MOVW    R0, 60(R13)             // save argc, argv away
20         MOVW    R1, 64(R13)
21
22         // set up g register
23         // g is R10
24         MOVW    $runtime·g0(SB), g
25         MOVW    $runtime·m0(SB), R8
26
27         // save m->g0 = g0
28         MOVW    g, m_g0(R8)
29         // save g->m = m0
30         MOVW    R8, g_m(g)
31
32         // create istack out of the OS stack
33         MOVW    $(-8192+104)(R13), R0
34         MOVW    R0, g_stackguard0(g)
35         MOVW    R0, g_stackguard1(g)
36         MOVW    R0, (g_stack+stack_lo)(g)
37         MOVW    R13, (g_stack+stack_hi)(g)
38
39         BL      runtime·emptyfunc(SB)  // fault if stack check is wrong
40
41 #ifndef GOOS_nacl
42         // if there is an _cgo_init, call it.
43         MOVW    _cgo_init(SB), R4
44         CMP     $0, R4
45         B.EQ    nocgo
46         MRC     15, 0, R0, C13, C0, 3   // load TLS base pointer
47         MOVW    R0, R3                  // arg 3: TLS base pointer
48         MOVW    $runtime·tlsg(SB), R2  // arg 2: tlsg
49         MOVW    $setg_gcc<>(SB), R1     // arg 1: setg
50         MOVW    g, R0                   // arg 0: G
51         BL      (R4) // will clobber R0-R3
52 #endif
53
54 nocgo:
55         // update stackguard after _cgo_init
56         MOVW    (g_stack+stack_lo)(g), R0
57         ADD     $const_StackGuard, R0
58         MOVW    R0, g_stackguard0(g)
59         MOVW    R0, g_stackguard1(g)
60
61         BL      runtime·checkgoarm(SB)
62         BL      runtime·check(SB)
63
64         // saved argc, argv
65         MOVW    60(R13), R0
66         MOVW    R0, 4(R13)
67         MOVW    64(R13), R1
68         MOVW    R1, 8(R13)
69         BL      runtime·args(SB)
70         BL      runtime·osinit(SB)
71         BL      runtime·schedinit(SB)
72
73         // create a new goroutine to start program
74         MOVW    $runtime·main·f(SB), R0
75         MOVW.W  R0, -4(R13)
76         MOVW    $8, R0
77         MOVW.W  R0, -4(R13)
78         MOVW    $0, R0
79         MOVW.W  R0, -4(R13)     // push $0 as guard
80         BL      runtime·newproc(SB)
81         MOVW    $12(R13), R13   // pop args and LR
82
83         // start this M
84         BL      runtime·mstart(SB)
85
86         MOVW    $1234, R0
87         MOVW    $1000, R1
88         MOVW    R0, (R1)        // fail hard
89
90 DATA    runtime·main·f+0(SB)/4,$runtime·main(SB)
91 GLOBL   runtime·main·f(SB),RODATA,$4
92
93 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
94         // gdb won't skip this breakpoint instruction automatically,
95         // so you must manually "set $pc+=4" to skip it and continue.
96 #ifdef GOOS_nacl
97         WORD    $0xe125be7f     // BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
98 #else
99         WORD    $0xe7f001f0     // undefined instruction that gdb understands is a software breakpoint
100 #endif
101         RET
102
103 TEXT runtime·asminit(SB),NOSPLIT,$0-0
104         // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
105         MOVB    runtime·goarm(SB), R11
106         CMP     $5, R11
107         BLE     4(PC)
108         WORD    $0xeef1ba10     // vmrs r11, fpscr
109         BIC     $(1<<24), R11
110         WORD    $0xeee1ba10     // vmsr fpscr, r11
111         RET
112
113 /*
114  *  go-routine
115  */
116
117 // void gosave(Gobuf*)
118 // save state in Gobuf; setjmp
119 TEXT runtime·gosave(SB),NOSPLIT,$-4-4
120         MOVW    0(FP), R0               // gobuf
121         MOVW    SP, gobuf_sp(R0)
122         MOVW    LR, gobuf_pc(R0)
123         MOVW    g, gobuf_g(R0)
124         MOVW    $0, R11
125         MOVW    R11, gobuf_lr(R0)
126         MOVW    R11, gobuf_ret(R0)
127         MOVW    R11, gobuf_ctxt(R0)
128         RET
129
130 // void gogo(Gobuf*)
131 // restore state from Gobuf; longjmp
132 TEXT runtime·gogo(SB),NOSPLIT,$-4-4
133         MOVW    0(FP), R1               // gobuf
134         MOVW    gobuf_g(R1), R0
135         BL      setg<>(SB)
136
137         // NOTE: We updated g above, and we are about to update SP.
138         // Until LR and PC are also updated, the g/SP/LR/PC quadruple
139         // are out of sync and must not be used as the basis of a traceback.
140         // Sigprof skips the traceback when SP is not within g's bounds,
141         // and when the PC is inside this function, runtime.gogo.
142         // Since we are about to update SP, until we complete runtime.gogo
143         // we must not leave this function. In particular, no calls
144         // after this point: it must be straight-line code until the
145         // final B instruction.
146         // See large comment in sigprof for more details.
147         MOVW    gobuf_sp(R1), SP        // restore SP
148         MOVW    gobuf_lr(R1), LR
149         MOVW    gobuf_ret(R1), R0
150         MOVW    gobuf_ctxt(R1), R7
151         MOVW    $0, R11
152         MOVW    R11, gobuf_sp(R1)       // clear to help garbage collector
153         MOVW    R11, gobuf_ret(R1)
154         MOVW    R11, gobuf_lr(R1)
155         MOVW    R11, gobuf_ctxt(R1)
156         MOVW    gobuf_pc(R1), R11
157         CMP     R11, R11 // set condition codes for == test, needed by stack split
158         B       (R11)
159
160 // func mcall(fn func(*g))
161 // Switch to m->g0's stack, call fn(g).
162 // Fn must never return.  It should gogo(&g->sched)
163 // to keep running g.
164 TEXT runtime·mcall(SB),NOSPLIT,$-4-4
165         // Save caller state in g->sched.
166         MOVW    SP, (g_sched+gobuf_sp)(g)
167         MOVW    LR, (g_sched+gobuf_pc)(g)
168         MOVW    $0, R11
169         MOVW    R11, (g_sched+gobuf_lr)(g)
170         MOVW    g, (g_sched+gobuf_g)(g)
171
172         // Switch to m->g0 & its stack, call fn.
173         MOVW    g, R1
174         MOVW    g_m(g), R8
175         MOVW    m_g0(R8), R0
176         BL      setg<>(SB)
177         CMP     g, R1
178         B.NE    2(PC)
179         B       runtime·badmcall(SB)
180         MOVB    runtime·iscgo(SB), R11
181         CMP     $0, R11
182         BL.NE   runtime·save_g(SB)
183         MOVW    fn+0(FP), R0
184         MOVW    (g_sched+gobuf_sp)(g), SP
185         SUB     $8, SP
186         MOVW    R1, 4(SP)
187         MOVW    R0, R7
188         MOVW    0(R0), R0
189         BL      (R0)
190         B       runtime·badmcall2(SB)
191         RET
192
193 // switchtoM is a dummy routine that onM leaves at the bottom
194 // of the G stack.  We need to distinguish the routine that
195 // lives at the bottom of the G stack from the one that lives
196 // at the top of the M stack because the one at the top of
197 // the M stack terminates the stack walk (see topofstack()).
198 TEXT runtime·switchtoM(SB),NOSPLIT,$0-0
199         MOVW    $0, R0
200         BL      (R0) // clobber lr to ensure push {lr} is kept
201         RET
202
203 // func onM_signalok(fn func())
204 TEXT runtime·onM_signalok(SB), NOSPLIT, $-4-4
205         MOVW    g_m(g), R1
206         MOVW    m_gsignal(R1), R2
207         CMP     g, R2
208         B.EQ    ongsignal
209         B       runtime·onM(SB)
210
211 ongsignal:
212         MOVW    fn+0(FP), R0
213         MOVW    R0, R7
214         MOVW    0(R0), R0
215         BL      (R0)
216         RET
217
218 // func onM(fn func())
219 TEXT runtime·onM(SB),NOSPLIT,$0-4
220         MOVW    fn+0(FP), R0    // R0 = fn
221         MOVW    g_m(g), R1      // R1 = m
222
223         MOVW    m_g0(R1), R2    // R2 = g0
224         CMP     g, R2
225         B.EQ    onm
226
227         MOVW    m_curg(R1), R3
228         CMP     g, R3
229         B.EQ    oncurg
230
231         // Not g0, not curg. Must be gsignal, but that's not allowed.
232         // Hide call from linker nosplit analysis.
233         MOVW    $runtime·badonm(SB), R0
234         BL      (R0)
235
236 oncurg:
237         // save our state in g->sched.  Pretend to
238         // be switchtoM if the G stack is scanned.
239         MOVW    $runtime·switchtoM(SB), R3
240         ADD     $4, R3, R3 // get past push {lr}
241         MOVW    R3, (g_sched+gobuf_pc)(g)
242         MOVW    SP, (g_sched+gobuf_sp)(g)
243         MOVW    LR, (g_sched+gobuf_lr)(g)
244         MOVW    g, (g_sched+gobuf_g)(g)
245
246         // switch to g0
247         MOVW    R0, R5
248         MOVW    R2, R0
249         BL      setg<>(SB)
250         MOVW    R5, R0
251         MOVW    (g_sched+gobuf_sp)(R2), R3
252         // make it look like mstart called onM on g0, to stop traceback
253         SUB     $4, R3, R3
254         MOVW    $runtime·mstart(SB), R4
255         MOVW    R4, 0(R3)
256         MOVW    R3, SP
257
258         // call target function
259         MOVW    R0, R7
260         MOVW    0(R0), R0
261         BL      (R0)
262
263         // switch back to g
264         MOVW    g_m(g), R1
265         MOVW    m_curg(R1), R0
266         BL      setg<>(SB)
267         MOVW    (g_sched+gobuf_sp)(g), SP
268         MOVW    $0, R3
269         MOVW    R3, (g_sched+gobuf_sp)(g)
270         RET
271
272 onm:
273         MOVW    R0, R7
274         MOVW    0(R0), R0
275         BL      (R0)
276         RET
277
278 /*
279  * support for morestack
280  */
281
282 // Called during function prolog when more stack is needed.
283 // R1 frame size
284 // R2 arg size
285 // R3 prolog's LR
286 // NB. we do not save R0 because we've forced 5c to pass all arguments
287 // on the stack.
288 // using frame size $-4 means do not save LR on stack.
289 //
290 // The traceback routines see morestack on a g0 as being
291 // the top of a stack (for example, morestack calling newstack
292 // calling the scheduler calling newm calling gc), so we must
293 // record an argument size. For that purpose, it has no arguments.
294 TEXT runtime·morestack(SB),NOSPLIT,$-4-0
295         // Cannot grow scheduler stack (m->g0).
296         MOVW    g_m(g), R8
297         MOVW    m_g0(R8), R4
298         CMP     g, R4
299         BL.EQ   runtime·abort(SB)
300
301         // Cannot grow signal stack (m->gsignal).
302         MOVW    m_gsignal(R8), R4
303         CMP     g, R4
304         BL.EQ   runtime·abort(SB)
305
306         // Called from f.
307         // Set g->sched to context in f.
308         MOVW    R7, (g_sched+gobuf_ctxt)(g)
309         MOVW    SP, (g_sched+gobuf_sp)(g)
310         MOVW    LR, (g_sched+gobuf_pc)(g)
311         MOVW    R3, (g_sched+gobuf_lr)(g)
312
313         // Called from f.
314         // Set m->morebuf to f's caller.
315         MOVW    R3, (m_morebuf+gobuf_pc)(R8)    // f's caller's PC
316         MOVW    SP, (m_morebuf+gobuf_sp)(R8)    // f's caller's SP
317         MOVW    $4(SP), R3                      // f's argument pointer
318         MOVW    g, (m_morebuf+gobuf_g)(R8)
319
320         // Call newstack on m->g0's stack.
321         MOVW    m_g0(R8), R0
322         BL      setg<>(SB)
323         MOVW    (g_sched+gobuf_sp)(g), SP
324         BL      runtime·newstack(SB)
325
326         // Not reached, but make sure the return PC from the call to newstack
327         // is still in this function, and not the beginning of the next.
328         RET
329
330 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0
331         MOVW    $0, R7
332         B runtime·morestack(SB)
333
334 // reflectcall: call a function with the given argument list
335 // func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
336 // we don't have variable-sized frames, so we use a small number
337 // of constant-sized-frame functions to encode a few bits of size in the pc.
338 // Caution: ugly multiline assembly macros in your future!
339
340 #define DISPATCH(NAME,MAXSIZE)          \
341         CMP     $MAXSIZE, R0;           \
342         B.HI    3(PC);                  \
343         MOVW    $NAME(SB), R1;          \
344         B       (R1)
345
346 TEXT ·reflectcall(SB),NOSPLIT,$-4-16
347         MOVW    argsize+8(FP), R0
348         DISPATCH(runtime·call16, 16)
349         DISPATCH(runtime·call32, 32)
350         DISPATCH(runtime·call64, 64)
351         DISPATCH(runtime·call128, 128)
352         DISPATCH(runtime·call256, 256)
353         DISPATCH(runtime·call512, 512)
354         DISPATCH(runtime·call1024, 1024)
355         DISPATCH(runtime·call2048, 2048)
356         DISPATCH(runtime·call4096, 4096)
357         DISPATCH(runtime·call8192, 8192)
358         DISPATCH(runtime·call16384, 16384)
359         DISPATCH(runtime·call32768, 32768)
360         DISPATCH(runtime·call65536, 65536)
361         DISPATCH(runtime·call131072, 131072)
362         DISPATCH(runtime·call262144, 262144)
363         DISPATCH(runtime·call524288, 524288)
364         DISPATCH(runtime·call1048576, 1048576)
365         DISPATCH(runtime·call2097152, 2097152)
366         DISPATCH(runtime·call4194304, 4194304)
367         DISPATCH(runtime·call8388608, 8388608)
368         DISPATCH(runtime·call16777216, 16777216)
369         DISPATCH(runtime·call33554432, 33554432)
370         DISPATCH(runtime·call67108864, 67108864)
371         DISPATCH(runtime·call134217728, 134217728)
372         DISPATCH(runtime·call268435456, 268435456)
373         DISPATCH(runtime·call536870912, 536870912)
374         DISPATCH(runtime·call1073741824, 1073741824)
375         MOVW    $runtime·badreflectcall(SB), R1
376         B       (R1)
377
378 #define CALLFN(NAME,MAXSIZE)                    \
379 TEXT NAME(SB), WRAPPER, $MAXSIZE-16;            \
380         NO_LOCAL_POINTERS;                      \
381         /* copy arguments to stack */           \
382         MOVW    argptr+4(FP), R0;               \
383         MOVW    argsize+8(FP), R2;              \
384         ADD     $4, SP, R1;                     \
385         CMP     $0, R2;                         \
386         B.EQ    5(PC);                          \
387         MOVBU.P 1(R0), R5;                      \
388         MOVBU.P R5, 1(R1);                      \
389         SUB     $1, R2, R2;                     \
390         B       -5(PC);                         \
391         /* call function */                     \
392         MOVW    f+0(FP), R7;                    \
393         MOVW    (R7), R0;                       \
394         PCDATA  $PCDATA_StackMapIndex, $0;      \
395         BL      (R0);                           \
396         /* copy return values back */           \
397         MOVW    argptr+4(FP), R0;               \
398         MOVW    argsize+8(FP), R2;              \
399         MOVW    retoffset+12(FP), R3;           \
400         ADD     $4, SP, R1;                     \
401         ADD     R3, R1;                         \
402         ADD     R3, R0;                         \
403         SUB     R3, R2;                         \
404         CMP     $0, R2;                         \
405         RET.EQ  ;                               \
406         MOVBU.P 1(R1), R5;                      \
407         MOVBU.P R5, 1(R0);                      \
408         SUB     $1, R2, R2;                     \
409         B       -5(PC)                          \
410
411 CALLFN(·call16, 16)
412 CALLFN(·call32, 32)
413 CALLFN(·call64, 64)
414 CALLFN(·call128, 128)
415 CALLFN(·call256, 256)
416 CALLFN(·call512, 512)
417 CALLFN(·call1024, 1024)
418 CALLFN(·call2048, 2048)
419 CALLFN(·call4096, 4096)
420 CALLFN(·call8192, 8192)
421 CALLFN(·call16384, 16384)
422 CALLFN(·call32768, 32768)
423 CALLFN(·call65536, 65536)
424 CALLFN(·call131072, 131072)
425 CALLFN(·call262144, 262144)
426 CALLFN(·call524288, 524288)
427 CALLFN(·call1048576, 1048576)
428 CALLFN(·call2097152, 2097152)
429 CALLFN(·call4194304, 4194304)
430 CALLFN(·call8388608, 8388608)
431 CALLFN(·call16777216, 16777216)
432 CALLFN(·call33554432, 33554432)
433 CALLFN(·call67108864, 67108864)
434 CALLFN(·call134217728, 134217728)
435 CALLFN(·call268435456, 268435456)
436 CALLFN(·call536870912, 536870912)
437 CALLFN(·call1073741824, 1073741824)
438
439 // void jmpdefer(fn, sp);
440 // called from deferreturn.
441 // 1. grab stored LR for caller
442 // 2. sub 4 bytes to get back to BL deferreturn
443 // 3. B to fn
444 // TODO(rsc): Push things on stack and then use pop
445 // to load all registers simultaneously, so that a profiling
446 // interrupt can never see mismatched SP/LR/PC.
447 // (And double-check that pop is atomic in that way.)
448 TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
449         MOVW    0(SP), LR
450         MOVW    $-4(LR), LR     // BL deferreturn
451         MOVW    fv+0(FP), R7
452         MOVW    argp+4(FP), SP
453         MOVW    $-4(SP), SP     // SP is 4 below argp, due to saved LR
454         MOVW    0(R7), R1
455         B       (R1)
456
457 // Save state of caller into g->sched. Smashes R11.
458 TEXT gosave<>(SB),NOSPLIT,$0
459         MOVW    LR, (g_sched+gobuf_pc)(g)
460         MOVW    R13, (g_sched+gobuf_sp)(g)
461         MOVW    $0, R11
462         MOVW    R11, (g_sched+gobuf_lr)(g)
463         MOVW    R11, (g_sched+gobuf_ret)(g)
464         MOVW    R11, (g_sched+gobuf_ctxt)(g)
465         RET
466
467 // asmcgocall(void(*fn)(void*), void *arg)
468 // Call fn(arg) on the scheduler stack,
469 // aligned appropriately for the gcc ABI.
470 // See cgocall.c for more details.
471 TEXT    ·asmcgocall(SB),NOSPLIT,$0-8
472         MOVW    fn+0(FP), R1
473         MOVW    arg+4(FP), R0
474         BL      asmcgocall<>(SB)
475         RET
476
477 TEXT ·asmcgocall_errno(SB),NOSPLIT,$0-12
478         MOVW    fn+0(FP), R1
479         MOVW    arg+4(FP), R0
480         BL      asmcgocall<>(SB)
481         MOVW    R0, ret+8(FP)
482         RET
483
484 TEXT asmcgocall<>(SB),NOSPLIT,$0-0
485         // fn in R1, arg in R0.
486         MOVW    R13, R2
487         MOVW    g, R4
488
489         // Figure out if we need to switch to m->g0 stack.
490         // We get called to create new OS threads too, and those
491         // come in on the m->g0 stack already.
492         MOVW    g_m(g), R8
493         MOVW    m_g0(R8), R3
494         CMP     R3, g
495         BEQ     g0
496         BL      gosave<>(SB)
497         MOVW    R0, R5
498         MOVW    R3, R0
499         BL      setg<>(SB)
500         MOVW    R5, R0
501         MOVW    (g_sched+gobuf_sp)(g), R13
502
503         // Now on a scheduling stack (a pthread-created stack).
504 g0:
505         SUB     $24, R13
506         BIC     $0x7, R13       // alignment for gcc ABI
507         MOVW    R4, 20(R13) // save old g
508         MOVW    (g_stack+stack_hi)(R4), R4
509         SUB     R2, R4
510         MOVW    R4, 16(R13)     // save depth in stack (can't just save SP, as stack might be copied during a callback)
511         BL      (R1)
512
513         // Restore registers, g, stack pointer.
514         MOVW    R0, R5
515         MOVW    20(R13), R0
516         BL      setg<>(SB)
517         MOVW    (g_stack+stack_hi)(g), R1
518         MOVW    16(R13), R2
519         SUB     R2, R1
520         MOVW    R5, R0
521         MOVW    R1, R13
522         RET
523
524 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
525 // Turn the fn into a Go func (by taking its address) and call
526 // cgocallback_gofunc.
527 TEXT runtime·cgocallback(SB),NOSPLIT,$12-12
528         MOVW    $fn+0(FP), R0
529         MOVW    R0, 4(R13)
530         MOVW    frame+4(FP), R0
531         MOVW    R0, 8(R13)
532         MOVW    framesize+8(FP), R0
533         MOVW    R0, 12(R13)
534         MOVW    $runtime·cgocallback_gofunc(SB), R0
535         BL      (R0)
536         RET
537
538 // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
539 // See cgocall.c for more details.
540 TEXT    ·cgocallback_gofunc(SB),NOSPLIT,$8-12
541         NO_LOCAL_POINTERS
542         
543         // Load m and g from thread-local storage.
544         MOVB    runtime·iscgo(SB), R0
545         CMP     $0, R0
546         BL.NE   runtime·load_g(SB)
547
548         // If g is nil, Go did not create the current thread.
549         // Call needm to obtain one for temporary use.
550         // In this case, we're running on the thread stack, so there's
551         // lots of space, but the linker doesn't know. Hide the call from
552         // the linker analysis by using an indirect call.
553         CMP     $0, g
554         B.NE    havem
555         MOVW    g, savedm-4(SP) // g is zero, so is m.
556         MOVW    $runtime·needm(SB), R0
557         BL      (R0)
558
559         // Set m->sched.sp = SP, so that if a panic happens
560         // during the function we are about to execute, it will
561         // have a valid SP to run on the g0 stack.
562         // The next few lines (after the havem label)
563         // will save this SP onto the stack and then write
564         // the same SP back to m->sched.sp. That seems redundant,
565         // but if an unrecovered panic happens, unwindm will
566         // restore the g->sched.sp from the stack location
567         // and then onM will try to use it. If we don't set it here,
568         // that restored SP will be uninitialized (typically 0) and
569         // will not be usable.
570         MOVW    g_m(g), R8
571         MOVW    m_g0(R8), R3
572         MOVW    R13, (g_sched+gobuf_sp)(R3)
573
574 havem:
575         MOVW    g_m(g), R8
576         MOVW    R8, savedm-4(SP)
577         // Now there's a valid m, and we're running on its m->g0.
578         // Save current m->g0->sched.sp on stack and then set it to SP.
579         // Save current sp in m->g0->sched.sp in preparation for
580         // switch back to m->curg stack.
581         // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP).
582         MOVW    m_g0(R8), R3
583         MOVW    (g_sched+gobuf_sp)(R3), R4
584         MOVW    R4, savedsp-8(SP)
585         MOVW    R13, (g_sched+gobuf_sp)(R3)
586
587         // Switch to m->curg stack and call runtime.cgocallbackg.
588         // Because we are taking over the execution of m->curg
589         // but *not* resuming what had been running, we need to
590         // save that information (m->curg->sched) so we can restore it.
591         // We can restore m->curg->sched.sp easily, because calling
592         // runtime.cgocallbackg leaves SP unchanged upon return.
593         // To save m->curg->sched.pc, we push it onto the stack.
594         // This has the added benefit that it looks to the traceback
595         // routine like cgocallbackg is going to return to that
596         // PC (because the frame we allocate below has the same
597         // size as cgocallback_gofunc's frame declared above)
598         // so that the traceback will seamlessly trace back into
599         // the earlier calls.
600         //
601         // In the new goroutine, -8(SP) and -4(SP) are unused.
602         MOVW    m_curg(R8), R0
603         BL      setg<>(SB)
604         MOVW    (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
605         MOVW    (g_sched+gobuf_pc)(g), R5
606         MOVW    R5, -12(R4)
607         MOVW    $-12(R4), R13
608         BL      runtime·cgocallbackg(SB)
609
610         // Restore g->sched (== m->curg->sched) from saved values.
611         MOVW    0(R13), R5
612         MOVW    R5, (g_sched+gobuf_pc)(g)
613         MOVW    $12(R13), R4
614         MOVW    R4, (g_sched+gobuf_sp)(g)
615
616         // Switch back to m->g0's stack and restore m->g0->sched.sp.
617         // (Unlike m->curg, the g0 goroutine never uses sched.pc,
618         // so we do not have to restore it.)
619         MOVW    g_m(g), R8
620         MOVW    m_g0(R8), R0
621         BL      setg<>(SB)
622         MOVW    (g_sched+gobuf_sp)(g), R13
623         MOVW    savedsp-8(SP), R4
624         MOVW    R4, (g_sched+gobuf_sp)(g)
625
626         // If the m on entry was nil, we called needm above to borrow an m
627         // for the duration of the call. Since the call is over, return it with dropm.
628         MOVW    savedm-4(SP), R6
629         CMP     $0, R6
630         B.NE    3(PC)
631         MOVW    $runtime·dropm(SB), R0
632         BL      (R0)
633
634         // Done!
635         RET
636
637 // void setg(G*); set g. for use by needm.
638 TEXT runtime·setg(SB),NOSPLIT,$-4-4
639         MOVW    gg+0(FP), R0
640         B       setg<>(SB)
641
642 TEXT setg<>(SB),NOSPLIT,$-4-0
643         MOVW    R0, g
644
645         // Save g to thread-local storage.
646         MOVB    runtime·iscgo(SB), R0
647         CMP     $0, R0
648         B.EQ    2(PC)
649         B       runtime·save_g(SB)
650
651         MOVW    g, R0
652         RET
653
654 TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
655         MOVW    0(SP), R0
656         MOVW    R0, ret+4(FP)
657         RET
658
659 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-4-8
660         MOVW    R14, ret+4(FP)
661         RET
662
663 TEXT runtime·setcallerpc(SB),NOSPLIT,$-4-8
664         MOVW    pc+4(FP), R0
665         MOVW    R0, 0(SP)
666         RET
667
668 TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4
669         MOVW    0(FP), R0
670         MOVW    $-4(R0), R0
671         MOVW    R0, ret+4(FP)
672         RET
673
674 // func gogetcallersp(p unsafe.Pointer) uintptr
675 TEXT runtime·gogetcallersp(SB),NOSPLIT,$-4-8
676         MOVW    0(FP), R0
677         MOVW    $-4(R0), R0
678         MOVW    R0, ret+4(FP)
679         RET
680
681 TEXT runtime·emptyfunc(SB),0,$0-0
682         RET
683
684 TEXT runtime·abort(SB),NOSPLIT,$-4-0
685         MOVW    $0, R0
686         MOVW    (R0), R1
687
688 // bool armcas(int32 *val, int32 old, int32 new)
689 // Atomically:
690 //      if(*val == old){
691 //              *val = new;
692 //              return 1;
693 //      }else
694 //              return 0;
695 //
696 // To implement runtime·cas in sys_$GOOS_arm.s
697 // using the native instructions, use:
698 //
699 //      TEXT runtime·cas(SB),NOSPLIT,$0
700 //              B       runtime·armcas(SB)
701 //
702 TEXT runtime·armcas(SB),NOSPLIT,$0-13
703         MOVW    valptr+0(FP), R1
704         MOVW    old+4(FP), R2
705         MOVW    new+8(FP), R3
706 casl:
707         LDREX   (R1), R0
708         CMP     R0, R2
709         BNE     casfail
710         STREX   R3, (R1), R0
711         CMP     $0, R0
712         BNE     casl
713         MOVW    $1, R0
714         MOVB    R0, ret+12(FP)
715         RET
716 casfail:
717         MOVW    $0, R0
718         MOVB    R0, ret+12(FP)
719         RET
720
721 TEXT runtime·casuintptr(SB),NOSPLIT,$0-13
722         B       runtime·cas(SB)
723
724 TEXT runtime·atomicloaduintptr(SB),NOSPLIT,$0-8
725         B       runtime·atomicload(SB)
726
727 TEXT runtime·atomicloaduint(SB),NOSPLIT,$0-8
728         B       runtime·atomicload(SB)
729
730 TEXT runtime·atomicstoreuintptr(SB),NOSPLIT,$0-8
731         B       runtime·atomicstore(SB)
732
733 // AES hashing not implemented for ARM
734 TEXT runtime·aeshash(SB),NOSPLIT,$-4-0
735         MOVW    $0, R0
736         MOVW    (R0), R1
737 TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0
738         MOVW    $0, R0
739         MOVW    (R0), R1
740 TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0
741         MOVW    $0, R0
742         MOVW    (R0), R1
743 TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0
744         MOVW    $0, R0
745         MOVW    (R0), R1
746
747 TEXT runtime·memeq(SB),NOSPLIT,$-4-13
748         MOVW    a+0(FP), R1
749         MOVW    b+4(FP), R2
750         MOVW    size+8(FP), R3
751         ADD     R1, R3, R6
752         MOVW    $1, R0
753         MOVB    R0, ret+12(FP)
754 loop:
755         CMP     R1, R6
756         RET.EQ
757         MOVBU.P 1(R1), R4
758         MOVBU.P 1(R2), R5
759         CMP     R4, R5
760         BEQ     loop
761
762         MOVW    $0, R0
763         MOVB    R0, ret+12(FP)
764         RET
765
766 // eqstring tests whether two strings are equal.
767 // See runtime_test.go:eqstring_generic for
768 // equivalent Go code.
769 TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
770         MOVW    s1len+4(FP), R0
771         MOVW    s2len+12(FP), R1
772         MOVW    $0, R7
773         CMP     R0, R1
774         MOVB.NE R7, v+16(FP)
775         RET.NE
776         MOVW    s1str+0(FP), R2
777         MOVW    s2str+8(FP), R3
778         MOVW    $1, R8
779         MOVB    R8, v+16(FP)
780         CMP     R2, R3
781         RET.EQ
782         ADD     R2, R0, R6
783 loop:
784         CMP     R2, R6
785         RET.EQ
786         MOVBU.P 1(R2), R4
787         MOVBU.P 1(R3), R5
788         CMP     R4, R5
789         BEQ     loop
790         MOVB    R7, v+16(FP)
791         RET
792
793 // void setg_gcc(G*); set g called from gcc.
794 TEXT setg_gcc<>(SB),NOSPLIT,$0
795         MOVW    R0, g
796         B               runtime·save_g(SB)
797
798 // TODO: share code with memeq?
799 TEXT bytes·Equal(SB),NOSPLIT,$0
800         MOVW    a_len+4(FP), R1
801         MOVW    b_len+16(FP), R3
802         
803         CMP     R1, R3          // unequal lengths are not equal
804         B.NE    notequal
805
806         MOVW    a+0(FP), R0
807         MOVW    b+12(FP), R2
808         ADD     R0, R1          // end
809
810 loop:
811         CMP     R0, R1
812         B.EQ    equal           // reached the end
813         MOVBU.P 1(R0), R4
814         MOVBU.P 1(R2), R5
815         CMP     R4, R5
816         B.EQ    loop
817
818 notequal:
819         MOVW    $0, R0
820         MOVBU   R0, ret+24(FP)
821         RET
822
823 equal:
824         MOVW    $1, R0
825         MOVBU   R0, ret+24(FP)
826         RET
827
828 TEXT bytes·IndexByte(SB),NOSPLIT,$0
829         MOVW    s+0(FP), R0
830         MOVW    s_len+4(FP), R1
831         MOVBU   c+12(FP), R2    // byte to find
832         MOVW    R0, R4          // store base for later
833         ADD     R0, R1          // end 
834
835 _loop:
836         CMP     R0, R1
837         B.EQ    _notfound
838         MOVBU.P 1(R0), R3
839         CMP     R2, R3
840         B.NE    _loop
841
842         SUB     $1, R0          // R0 will be one beyond the position we want
843         SUB     R4, R0          // remove base
844         MOVW    R0, ret+16(FP) 
845         RET
846
847 _notfound:
848         MOVW    $-1, R0
849         MOVW    R0, ret+16(FP)
850         RET
851
852 TEXT strings·IndexByte(SB),NOSPLIT,$0
853         MOVW    s+0(FP), R0
854         MOVW    s_len+4(FP), R1
855         MOVBU   c+8(FP), R2     // byte to find
856         MOVW    R0, R4          // store base for later
857         ADD     R0, R1          // end 
858
859 _sib_loop:
860         CMP     R0, R1
861         B.EQ    _sib_notfound
862         MOVBU.P 1(R0), R3
863         CMP     R2, R3
864         B.NE    _sib_loop
865
866         SUB     $1, R0          // R0 will be one beyond the position we want
867         SUB     R4, R0          // remove base
868         MOVW    R0, ret+12(FP) 
869         RET
870
871 _sib_notfound:
872         MOVW    $-1, R0
873         MOVW    R0, ret+12(FP)
874         RET
875
876 // A Duff's device for zeroing memory.
877 // The compiler jumps to computed addresses within
878 // this routine to zero chunks of memory.  Do not
879 // change this code without also changing the code
880 // in ../../cmd/5g/ggen.c:clearfat.
881 // R0: zero
882 // R1: ptr to memory to be zeroed
883 // R1 is updated as a side effect.
884 TEXT runtime·duffzero(SB),NOSPLIT,$0-0
885         MOVW.P  R0, 4(R1)
886         MOVW.P  R0, 4(R1)
887         MOVW.P  R0, 4(R1)
888         MOVW.P  R0, 4(R1)
889         MOVW.P  R0, 4(R1)
890         MOVW.P  R0, 4(R1)
891         MOVW.P  R0, 4(R1)
892         MOVW.P  R0, 4(R1)
893         MOVW.P  R0, 4(R1)
894         MOVW.P  R0, 4(R1)
895         MOVW.P  R0, 4(R1)
896         MOVW.P  R0, 4(R1)
897         MOVW.P  R0, 4(R1)
898         MOVW.P  R0, 4(R1)
899         MOVW.P  R0, 4(R1)
900         MOVW.P  R0, 4(R1)
901         MOVW.P  R0, 4(R1)
902         MOVW.P  R0, 4(R1)
903         MOVW.P  R0, 4(R1)
904         MOVW.P  R0, 4(R1)
905         MOVW.P  R0, 4(R1)
906         MOVW.P  R0, 4(R1)
907         MOVW.P  R0, 4(R1)
908         MOVW.P  R0, 4(R1)
909         MOVW.P  R0, 4(R1)
910         MOVW.P  R0, 4(R1)
911         MOVW.P  R0, 4(R1)
912         MOVW.P  R0, 4(R1)
913         MOVW.P  R0, 4(R1)
914         MOVW.P  R0, 4(R1)
915         MOVW.P  R0, 4(R1)
916         MOVW.P  R0, 4(R1)
917         MOVW.P  R0, 4(R1)
918         MOVW.P  R0, 4(R1)
919         MOVW.P  R0, 4(R1)
920         MOVW.P  R0, 4(R1)
921         MOVW.P  R0, 4(R1)
922         MOVW.P  R0, 4(R1)
923         MOVW.P  R0, 4(R1)
924         MOVW.P  R0, 4(R1)
925         MOVW.P  R0, 4(R1)
926         MOVW.P  R0, 4(R1)
927         MOVW.P  R0, 4(R1)
928         MOVW.P  R0, 4(R1)
929         MOVW.P  R0, 4(R1)
930         MOVW.P  R0, 4(R1)
931         MOVW.P  R0, 4(R1)
932         MOVW.P  R0, 4(R1)
933         MOVW.P  R0, 4(R1)
934         MOVW.P  R0, 4(R1)
935         MOVW.P  R0, 4(R1)
936         MOVW.P  R0, 4(R1)
937         MOVW.P  R0, 4(R1)
938         MOVW.P  R0, 4(R1)
939         MOVW.P  R0, 4(R1)
940         MOVW.P  R0, 4(R1)
941         MOVW.P  R0, 4(R1)
942         MOVW.P  R0, 4(R1)
943         MOVW.P  R0, 4(R1)
944         MOVW.P  R0, 4(R1)
945         MOVW.P  R0, 4(R1)
946         MOVW.P  R0, 4(R1)
947         MOVW.P  R0, 4(R1)
948         MOVW.P  R0, 4(R1)
949         MOVW.P  R0, 4(R1)
950         MOVW.P  R0, 4(R1)
951         MOVW.P  R0, 4(R1)
952         MOVW.P  R0, 4(R1)
953         MOVW.P  R0, 4(R1)
954         MOVW.P  R0, 4(R1)
955         MOVW.P  R0, 4(R1)
956         MOVW.P  R0, 4(R1)
957         MOVW.P  R0, 4(R1)
958         MOVW.P  R0, 4(R1)
959         MOVW.P  R0, 4(R1)
960         MOVW.P  R0, 4(R1)
961         MOVW.P  R0, 4(R1)
962         MOVW.P  R0, 4(R1)
963         MOVW.P  R0, 4(R1)
964         MOVW.P  R0, 4(R1)
965         MOVW.P  R0, 4(R1)
966         MOVW.P  R0, 4(R1)
967         MOVW.P  R0, 4(R1)
968         MOVW.P  R0, 4(R1)
969         MOVW.P  R0, 4(R1)
970         MOVW.P  R0, 4(R1)
971         MOVW.P  R0, 4(R1)
972         MOVW.P  R0, 4(R1)
973         MOVW.P  R0, 4(R1)
974         MOVW.P  R0, 4(R1)
975         MOVW.P  R0, 4(R1)
976         MOVW.P  R0, 4(R1)
977         MOVW.P  R0, 4(R1)
978         MOVW.P  R0, 4(R1)
979         MOVW.P  R0, 4(R1)
980         MOVW.P  R0, 4(R1)
981         MOVW.P  R0, 4(R1)
982         MOVW.P  R0, 4(R1)
983         MOVW.P  R0, 4(R1)
984         MOVW.P  R0, 4(R1)
985         MOVW.P  R0, 4(R1)
986         MOVW.P  R0, 4(R1)
987         MOVW.P  R0, 4(R1)
988         MOVW.P  R0, 4(R1)
989         MOVW.P  R0, 4(R1)
990         MOVW.P  R0, 4(R1)
991         MOVW.P  R0, 4(R1)
992         MOVW.P  R0, 4(R1)
993         MOVW.P  R0, 4(R1)
994         MOVW.P  R0, 4(R1)
995         MOVW.P  R0, 4(R1)
996         MOVW.P  R0, 4(R1)
997         MOVW.P  R0, 4(R1)
998         MOVW.P  R0, 4(R1)
999         MOVW.P  R0, 4(R1)
1000         MOVW.P  R0, 4(R1)
1001         MOVW.P  R0, 4(R1)
1002         MOVW.P  R0, 4(R1)
1003         MOVW.P  R0, 4(R1)
1004         MOVW.P  R0, 4(R1)
1005         MOVW.P  R0, 4(R1)
1006         MOVW.P  R0, 4(R1)
1007         MOVW.P  R0, 4(R1)
1008         MOVW.P  R0, 4(R1)
1009         MOVW.P  R0, 4(R1)
1010         MOVW.P  R0, 4(R1)
1011         MOVW.P  R0, 4(R1)
1012         MOVW.P  R0, 4(R1)
1013         RET
1014
1015 // A Duff's device for copying memory.
1016 // The compiler jumps to computed addresses within
1017 // this routine to copy chunks of memory.  Source
1018 // and destination must not overlap.  Do not
1019 // change this code without also changing the code
1020 // in ../../cmd/5g/cgen.c:sgen.
1021 // R0: scratch space
1022 // R1: ptr to source memory
1023 // R2: ptr to destination memory
1024 // R1 and R2 are updated as a side effect
1025 TEXT runtime·duffcopy(SB),NOSPLIT,$0-0
1026         MOVW.P  4(R1), R0
1027         MOVW.P  R0, 4(R2)
1028         MOVW.P  4(R1), R0
1029         MOVW.P  R0, 4(R2)
1030         MOVW.P  4(R1), R0
1031         MOVW.P  R0, 4(R2)
1032         MOVW.P  4(R1), R0
1033         MOVW.P  R0, 4(R2)
1034         MOVW.P  4(R1), R0
1035         MOVW.P  R0, 4(R2)
1036         MOVW.P  4(R1), R0
1037         MOVW.P  R0, 4(R2)
1038         MOVW.P  4(R1), R0
1039         MOVW.P  R0, 4(R2)
1040         MOVW.P  4(R1), R0
1041         MOVW.P  R0, 4(R2)
1042         MOVW.P  4(R1), R0
1043         MOVW.P  R0, 4(R2)
1044         MOVW.P  4(R1), R0
1045         MOVW.P  R0, 4(R2)
1046         MOVW.P  4(R1), R0
1047         MOVW.P  R0, 4(R2)
1048         MOVW.P  4(R1), R0
1049         MOVW.P  R0, 4(R2)
1050         MOVW.P  4(R1), R0
1051         MOVW.P  R0, 4(R2)
1052         MOVW.P  4(R1), R0
1053         MOVW.P  R0, 4(R2)
1054         MOVW.P  4(R1), R0
1055         MOVW.P  R0, 4(R2)
1056         MOVW.P  4(R1), R0
1057         MOVW.P  R0, 4(R2)
1058         MOVW.P  4(R1), R0
1059         MOVW.P  R0, 4(R2)
1060         MOVW.P  4(R1), R0
1061         MOVW.P  R0, 4(R2)
1062         MOVW.P  4(R1), R0
1063         MOVW.P  R0, 4(R2)
1064         MOVW.P  4(R1), R0
1065         MOVW.P  R0, 4(R2)
1066         MOVW.P  4(R1), R0
1067         MOVW.P  R0, 4(R2)
1068         MOVW.P  4(R1), R0
1069         MOVW.P  R0, 4(R2)
1070         MOVW.P  4(R1), R0
1071         MOVW.P  R0, 4(R2)
1072         MOVW.P  4(R1), R0
1073         MOVW.P  R0, 4(R2)
1074         MOVW.P  4(R1), R0
1075         MOVW.P  R0, 4(R2)
1076         MOVW.P  4(R1), R0
1077         MOVW.P  R0, 4(R2)
1078         MOVW.P  4(R1), R0
1079         MOVW.P  R0, 4(R2)
1080         MOVW.P  4(R1), R0
1081         MOVW.P  R0, 4(R2)
1082         MOVW.P  4(R1), R0
1083         MOVW.P  R0, 4(R2)
1084         MOVW.P  4(R1), R0
1085         MOVW.P  R0, 4(R2)
1086         MOVW.P  4(R1), R0
1087         MOVW.P  R0, 4(R2)
1088         MOVW.P  4(R1), R0
1089         MOVW.P  R0, 4(R2)
1090         MOVW.P  4(R1), R0
1091         MOVW.P  R0, 4(R2)
1092         MOVW.P  4(R1), R0
1093         MOVW.P  R0, 4(R2)
1094         MOVW.P  4(R1), R0
1095         MOVW.P  R0, 4(R2)
1096         MOVW.P  4(R1), R0
1097         MOVW.P  R0, 4(R2)
1098         MOVW.P  4(R1), R0
1099         MOVW.P  R0, 4(R2)
1100         MOVW.P  4(R1), R0
1101         MOVW.P  R0, 4(R2)
1102         MOVW.P  4(R1), R0
1103         MOVW.P  R0, 4(R2)
1104         MOVW.P  4(R1), R0
1105         MOVW.P  R0, 4(R2)
1106         MOVW.P  4(R1), R0
1107         MOVW.P  R0, 4(R2)
1108         MOVW.P  4(R1), R0
1109         MOVW.P  R0, 4(R2)
1110         MOVW.P  4(R1), R0
1111         MOVW.P  R0, 4(R2)
1112         MOVW.P  4(R1), R0
1113         MOVW.P  R0, 4(R2)
1114         MOVW.P  4(R1), R0
1115         MOVW.P  R0, 4(R2)
1116         MOVW.P  4(R1), R0
1117         MOVW.P  R0, 4(R2)
1118         MOVW.P  4(R1), R0
1119         MOVW.P  R0, 4(R2)
1120         MOVW.P  4(R1), R0
1121         MOVW.P  R0, 4(R2)
1122         MOVW.P  4(R1), R0
1123         MOVW.P  R0, 4(R2)
1124         MOVW.P  4(R1), R0
1125         MOVW.P  R0, 4(R2)
1126         MOVW.P  4(R1), R0
1127         MOVW.P  R0, 4(R2)
1128         MOVW.P  4(R1), R0
1129         MOVW.P  R0, 4(R2)
1130         MOVW.P  4(R1), R0
1131         MOVW.P  R0, 4(R2)
1132         MOVW.P  4(R1), R0
1133         MOVW.P  R0, 4(R2)
1134         MOVW.P  4(R1), R0
1135         MOVW.P  R0, 4(R2)
1136         MOVW.P  4(R1), R0
1137         MOVW.P  R0, 4(R2)
1138         MOVW.P  4(R1), R0
1139         MOVW.P  R0, 4(R2)
1140         MOVW.P  4(R1), R0
1141         MOVW.P  R0, 4(R2)
1142         MOVW.P  4(R1), R0
1143         MOVW.P  R0, 4(R2)
1144         MOVW.P  4(R1), R0
1145         MOVW.P  R0, 4(R2)
1146         MOVW.P  4(R1), R0
1147         MOVW.P  R0, 4(R2)
1148         MOVW.P  4(R1), R0
1149         MOVW.P  R0, 4(R2)
1150         MOVW.P  4(R1), R0
1151         MOVW.P  R0, 4(R2)
1152         MOVW.P  4(R1), R0
1153         MOVW.P  R0, 4(R2)
1154         MOVW.P  4(R1), R0
1155         MOVW.P  R0, 4(R2)
1156         MOVW.P  4(R1), R0
1157         MOVW.P  R0, 4(R2)
1158         MOVW.P  4(R1), R0
1159         MOVW.P  R0, 4(R2)
1160         MOVW.P  4(R1), R0
1161         MOVW.P  R0, 4(R2)
1162         MOVW.P  4(R1), R0
1163         MOVW.P  R0, 4(R2)
1164         MOVW.P  4(R1), R0
1165         MOVW.P  R0, 4(R2)
1166         MOVW.P  4(R1), R0
1167         MOVW.P  R0, 4(R2)
1168         MOVW.P  4(R1), R0
1169         MOVW.P  R0, 4(R2)
1170         MOVW.P  4(R1), R0
1171         MOVW.P  R0, 4(R2)
1172         MOVW.P  4(R1), R0
1173         MOVW.P  R0, 4(R2)
1174         MOVW.P  4(R1), R0
1175         MOVW.P  R0, 4(R2)
1176         MOVW.P  4(R1), R0
1177         MOVW.P  R0, 4(R2)
1178         MOVW.P  4(R1), R0
1179         MOVW.P  R0, 4(R2)
1180         MOVW.P  4(R1), R0
1181         MOVW.P  R0, 4(R2)
1182         MOVW.P  4(R1), R0
1183         MOVW.P  R0, 4(R2)
1184         MOVW.P  4(R1), R0
1185         MOVW.P  R0, 4(R2)
1186         MOVW.P  4(R1), R0
1187         MOVW.P  R0, 4(R2)
1188         MOVW.P  4(R1), R0
1189         MOVW.P  R0, 4(R2)
1190         MOVW.P  4(R1), R0
1191         MOVW.P  R0, 4(R2)
1192         MOVW.P  4(R1), R0
1193         MOVW.P  R0, 4(R2)
1194         MOVW.P  4(R1), R0
1195         MOVW.P  R0, 4(R2)
1196         MOVW.P  4(R1), R0
1197         MOVW.P  R0, 4(R2)
1198         MOVW.P  4(R1), R0
1199         MOVW.P  R0, 4(R2)
1200         MOVW.P  4(R1), R0
1201         MOVW.P  R0, 4(R2)
1202         MOVW.P  4(R1), R0
1203         MOVW.P  R0, 4(R2)
1204         MOVW.P  4(R1), R0
1205         MOVW.P  R0, 4(R2)
1206         MOVW.P  4(R1), R0
1207         MOVW.P  R0, 4(R2)
1208         MOVW.P  4(R1), R0
1209         MOVW.P  R0, 4(R2)
1210         MOVW.P  4(R1), R0
1211         MOVW.P  R0, 4(R2)
1212         MOVW.P  4(R1), R0
1213         MOVW.P  R0, 4(R2)
1214         MOVW.P  4(R1), R0
1215         MOVW.P  R0, 4(R2)
1216         MOVW.P  4(R1), R0
1217         MOVW.P  R0, 4(R2)
1218         MOVW.P  4(R1), R0
1219         MOVW.P  R0, 4(R2)
1220         MOVW.P  4(R1), R0
1221         MOVW.P  R0, 4(R2)
1222         MOVW.P  4(R1), R0
1223         MOVW.P  R0, 4(R2)
1224         MOVW.P  4(R1), R0
1225         MOVW.P  R0, 4(R2)
1226         MOVW.P  4(R1), R0
1227         MOVW.P  R0, 4(R2)
1228         MOVW.P  4(R1), R0
1229         MOVW.P  R0, 4(R2)
1230         MOVW.P  4(R1), R0
1231         MOVW.P  R0, 4(R2)
1232         MOVW.P  4(R1), R0
1233         MOVW.P  R0, 4(R2)
1234         MOVW.P  4(R1), R0
1235         MOVW.P  R0, 4(R2)
1236         MOVW.P  4(R1), R0
1237         MOVW.P  R0, 4(R2)
1238         MOVW.P  4(R1), R0
1239         MOVW.P  R0, 4(R2)
1240         MOVW.P  4(R1), R0
1241         MOVW.P  R0, 4(R2)
1242         MOVW.P  4(R1), R0
1243         MOVW.P  R0, 4(R2)
1244         MOVW.P  4(R1), R0
1245         MOVW.P  R0, 4(R2)
1246         MOVW.P  4(R1), R0
1247         MOVW.P  R0, 4(R2)
1248         MOVW.P  4(R1), R0
1249         MOVW.P  R0, 4(R2)
1250         MOVW.P  4(R1), R0
1251         MOVW.P  R0, 4(R2)
1252         MOVW.P  4(R1), R0
1253         MOVW.P  R0, 4(R2)
1254         MOVW.P  4(R1), R0
1255         MOVW.P  R0, 4(R2)
1256         MOVW.P  4(R1), R0
1257         MOVW.P  R0, 4(R2)
1258         MOVW.P  4(R1), R0
1259         MOVW.P  R0, 4(R2)
1260         MOVW.P  4(R1), R0
1261         MOVW.P  R0, 4(R2)
1262         MOVW.P  4(R1), R0
1263         MOVW.P  R0, 4(R2)
1264         MOVW.P  4(R1), R0
1265         MOVW.P  R0, 4(R2)
1266         MOVW.P  4(R1), R0
1267         MOVW.P  R0, 4(R2)
1268         MOVW.P  4(R1), R0
1269         MOVW.P  R0, 4(R2)
1270         MOVW.P  4(R1), R0
1271         MOVW.P  R0, 4(R2)
1272         MOVW.P  4(R1), R0
1273         MOVW.P  R0, 4(R2)
1274         MOVW.P  4(R1), R0
1275         MOVW.P  R0, 4(R2)
1276         MOVW.P  4(R1), R0
1277         MOVW.P  R0, 4(R2)
1278         MOVW.P  4(R1), R0
1279         MOVW.P  R0, 4(R2)
1280         MOVW.P  4(R1), R0
1281         MOVW.P  R0, 4(R2)
1282         RET
1283
1284 TEXT runtime·fastrand1(SB),NOSPLIT,$-4-4
1285         MOVW    g_m(g), R1
1286         MOVW    m_fastrand(R1), R0
1287         ADD.S   R0, R0
1288         EOR.MI  $0x88888eef, R0
1289         MOVW    R0, m_fastrand(R1)
1290         MOVW    R0, ret+0(FP)
1291         RET
1292
1293 TEXT runtime·return0(SB),NOSPLIT,$0
1294         MOVW    $0, R0
1295         RET
1296
1297 TEXT runtime·procyield(SB),NOSPLIT,$-4
1298         MOVW    cycles+0(FP), R1
1299         MOVW    $0, R0
1300 yieldloop:
1301         CMP     R0, R1
1302         B.NE    2(PC)
1303         RET
1304         SUB     $1, R1
1305         B yieldloop
1306
1307 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
1308 // Must obey the gcc calling convention.
1309 TEXT _cgo_topofstack(SB),NOSPLIT,$8
1310         // R11 and g register are clobbered by load_g.  They are
1311         // callee-save in the gcc calling convention, so save them here.
1312         MOVW    R11, saveR11-4(SP)
1313         MOVW    g, saveG-8(SP)
1314         
1315         BL      runtime·load_g(SB)
1316         MOVW    g_m(g), R0
1317         MOVW    m_curg(R0), R0
1318         MOVW    (g_stack+stack_hi)(R0), R0
1319         
1320         MOVW    saveG-8(SP), g
1321         MOVW    saveR11-4(SP), R11
1322         RET