]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/asm_power64x.s
[dev.cc] all: merge default (95f5614b4648) into dev.cc
[gostls13.git] / src / runtime / asm_power64x.s
1 // Copyright 2014 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 // +build power64 power64le
6
7 #include "go_asm.h"
8 #include "go_tls.h"
9 #include "funcdata.h"
10 #include "textflag.h"
11
12 TEXT runtime·rt0_go(SB),NOSPLIT,$0
13         // initialize essential registers
14         BL      runtime·reginit(SB)
15
16         SUB     $24, R1
17         MOVW    R3, 8(R1) // argc
18         MOVD    R4, 16(R1) // argv
19
20         // create istack out of the given (operating system) stack.
21         // _cgo_init may update stackguard.
22         MOVD    $runtime·g0(SB), g
23         MOVD    $(-64*1024), R31
24         ADD     R31, R1, R3
25         MOVD    R3, g_stackguard0(g)
26         MOVD    R3, g_stackguard1(g)
27         MOVD    R3, (g_stack+stack_lo)(g)
28         MOVD    R1, (g_stack+stack_hi)(g)
29
30         // TODO: if there is a _cgo_init, call it.
31         // TODO: add TLS
32
33         // set the per-goroutine and per-mach "registers"
34         MOVD    $runtime·m0(SB), R3
35
36         // save m->g0 = g0
37         MOVD    g, m_g0(R3)
38         // save m0 to g0->m
39         MOVD    R3, g_m(g)
40
41         BL      runtime·check(SB)
42
43         // args are already prepared
44         BL      runtime·args(SB)
45         BL      runtime·osinit(SB)
46         BL      runtime·schedinit(SB)
47
48         // create a new goroutine to start program
49         MOVD    $runtime·main·f(SB), R3               // entry
50         MOVDU   R3, -8(R1)
51         MOVDU   R0, -8(R1)
52         MOVDU   R0, -8(R1)
53         BL      runtime·newproc(SB)
54         ADD     $24, R1
55
56         // start this M
57         BL      runtime·mstart(SB)
58
59         MOVD    R0, 1(R0)
60         RETURN
61
62 DATA    runtime·main·f+0(SB)/8,$runtime·main(SB)
63 GLOBL   runtime·main·f(SB),RODATA,$8
64
65 TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
66         MOVD    R0, 2(R0) // TODO: TD
67         RETURN
68
69 TEXT runtime·asminit(SB),NOSPLIT,$-8-0
70         RETURN
71
72 TEXT runtime·reginit(SB),NOSPLIT,$-8-0
73         // set R0 to zero, it's expected by the toolchain
74         XOR R0, R0
75         // initialize essential FP registers
76         FMOVD   $4503601774854144.0, F27
77         FMOVD   $0.5, F29
78         FSUB    F29, F29, F28
79         FADD    F29, F29, F30
80         FADD    F30, F30, F31
81         RETURN
82
83 /*
84  *  go-routine
85  */
86
87 // void gosave(Gobuf*)
88 // save state in Gobuf; setjmp
89 TEXT runtime·gosave(SB), NOSPLIT, $-8-8
90         MOVD    buf+0(FP), R3
91         MOVD    R1, gobuf_sp(R3)
92         MOVD    LR, R31
93         MOVD    R31, gobuf_pc(R3)
94         MOVD    g, gobuf_g(R3)
95         MOVD    R0, gobuf_lr(R3)
96         MOVD    R0, gobuf_ret(R3)
97         MOVD    R0, gobuf_ctxt(R3)
98         RETURN
99
100 // void gogo(Gobuf*)
101 // restore state from Gobuf; longjmp
102 TEXT runtime·gogo(SB), NOSPLIT, $-8-8
103         MOVD    buf+0(FP), R5
104         MOVD    gobuf_g(R5), g  // make sure g is not nil
105         MOVD    0(g), R4
106         MOVD    gobuf_sp(R5), R1
107         MOVD    gobuf_lr(R5), R31
108         MOVD    R31, LR
109         MOVD    gobuf_ret(R5), R3
110         MOVD    gobuf_ctxt(R5), R11
111         MOVD    R0, gobuf_sp(R5)
112         MOVD    R0, gobuf_ret(R5)
113         MOVD    R0, gobuf_lr(R5)
114         MOVD    R0, gobuf_ctxt(R5)
115         CMP     R0, R0 // set condition codes for == test, needed by stack split
116         MOVD    gobuf_pc(R5), R31
117         MOVD    R31, CTR
118         BR      (CTR)
119
120 // void mcall(fn func(*g))
121 // Switch to m->g0's stack, call fn(g).
122 // Fn must never return.  It should gogo(&g->sched)
123 // to keep running g.
124 TEXT runtime·mcall(SB), NOSPLIT, $-8-8
125         // Save caller state in g->sched
126         MOVD    R1, (g_sched+gobuf_sp)(g)
127         MOVD    LR, R31
128         MOVD    R31, (g_sched+gobuf_pc)(g)
129         MOVD    R0, (g_sched+gobuf_lr)(g)
130         MOVD    g, (g_sched+gobuf_g)(g)
131
132         // Switch to m->g0 & its stack, call fn.
133         MOVD    g, R3
134         MOVD    g_m(g), R8
135         MOVD    m_g0(R8), g
136         CMP     g, R3
137         BNE     2(PC)
138         BR      runtime·badmcall(SB)
139         MOVD    fn+0(FP), R11                   // context
140         MOVD    0(R11), R4                      // code pointer
141         MOVD    R4, CTR
142         MOVD    (g_sched+gobuf_sp)(g), R1       // sp = m->g0->sched.sp
143         MOVDU   R3, -8(R1)
144         MOVDU   R0, -8(R1)
145         BL      (CTR)
146         BR      runtime·badmcall2(SB)
147
148 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
149 // of the G stack.  We need to distinguish the routine that
150 // lives at the bottom of the G stack from the one that lives
151 // at the top of the system stack because the one at the top of
152 // the system stack terminates the stack walk (see topofstack()).
153 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
154         UNDEF
155         BL      (LR)    // make sure this function is not leaf
156         RETURN
157
158 // func systemstack(fn func())
159 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
160         MOVD    fn+0(FP), R3    // R3 = fn
161         MOVD    R3, R11         // context
162         MOVD    g_m(g), R4      // R4 = m
163
164         MOVD    m_gsignal(R4), R5       // R5 = gsignal
165         CMP     g, R5
166         BEQ     noswitch
167
168         MOVD    m_g0(R4), R5    // R5 = g0
169         CMP     g, R5
170         BEQ     noswitch
171
172         MOVD    m_curg(R4), R6
173         CMP     g, R6
174         BEQ     switch
175
176         // Bad: g is not gsignal, not g0, not curg. What is it?
177         // Hide call from linker nosplit analysis.
178         MOVD    $runtime·badsystemstack(SB), R3
179         MOVD    R3, CTR
180         BL      (CTR)
181
182 switch:
183         // save our state in g->sched.  Pretend to
184         // be systemstack_switch if the G stack is scanned.
185         MOVD    $runtime·systemstack_switch(SB), R6
186         ADD     $8, R6  // get past prologue
187         MOVD    R6, (g_sched+gobuf_pc)(g)
188         MOVD    R1, (g_sched+gobuf_sp)(g)
189         MOVD    R0, (g_sched+gobuf_lr)(g)
190         MOVD    g, (g_sched+gobuf_g)(g)
191
192         // switch to g0
193         MOVD    R5, g
194         MOVD    (g_sched+gobuf_sp)(g), R3
195         // make it look like mstart called systemstack on g0, to stop traceback
196         SUB     $8, R3
197         MOVD    $runtime·mstart(SB), R4
198         MOVD    R4, 0(R3)
199         MOVD    R3, R1
200
201         // call target function
202         MOVD    0(R11), R3      // code pointer
203         MOVD    R3, CTR
204         BL      (CTR)
205
206         // switch back to g
207         MOVD    g_m(g), R3
208         MOVD    m_curg(R3), g
209         MOVD    (g_sched+gobuf_sp)(g), R1
210         MOVD    R0, (g_sched+gobuf_sp)(g)
211         RETURN
212
213 noswitch:
214         // already on m stack, just call directly
215         MOVD    0(R11), R3      // code pointer
216         MOVD    R3, CTR
217         BL      (CTR)
218         RETURN
219
220 /*
221  * support for morestack
222  */
223
224 // Called during function prolog when more stack is needed.
225 // Caller has already loaded:
226 // R3: framesize, R4: argsize, R5: LR
227 //
228 // The traceback routines see morestack on a g0 as being
229 // the top of a stack (for example, morestack calling newstack
230 // calling the scheduler calling newm calling gc), so we must
231 // record an argument size. For that purpose, it has no arguments.
232 TEXT runtime·morestack(SB),NOSPLIT,$-8-0
233         // Cannot grow scheduler stack (m->g0).
234         MOVD    g_m(g), R7
235         MOVD    m_g0(R7), R8
236         CMP     g, R8
237         BNE     2(PC)
238         BL      runtime·abort(SB)
239
240         // Cannot grow signal stack (m->gsignal).
241         MOVD    m_gsignal(R7), R8
242         CMP     g, R8
243         BNE     2(PC)
244         BL      runtime·abort(SB)
245
246         // Called from f.
247         // Set g->sched to context in f.
248         MOVD    R11, (g_sched+gobuf_ctxt)(g)
249         MOVD    R1, (g_sched+gobuf_sp)(g)
250         MOVD    LR, R8
251         MOVD    R8, (g_sched+gobuf_pc)(g)
252         MOVD    R5, (g_sched+gobuf_lr)(g)
253
254         // Called from f.
255         // Set m->morebuf to f's caller.
256         MOVD    R5, (m_morebuf+gobuf_pc)(R7)    // f's caller's PC
257         MOVD    R1, (m_morebuf+gobuf_sp)(R7)    // f's caller's SP
258         MOVD    g, (m_morebuf+gobuf_g)(R7)
259
260         // Call newstack on m->g0's stack.
261         MOVD    m_g0(R7), g
262         MOVD    (g_sched+gobuf_sp)(g), R1
263         BL      runtime·newstack(SB)
264
265         // Not reached, but make sure the return PC from the call to newstack
266         // is still in this function, and not the beginning of the next.
267         UNDEF
268
269 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
270         MOVD    R0, R11
271         BR      runtime·morestack(SB)
272
273 // reflectcall: call a function with the given argument list
274 // func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
275 // we don't have variable-sized frames, so we use a small number
276 // of constant-sized-frame functions to encode a few bits of size in the pc.
277 // Caution: ugly multiline assembly macros in your future!
278
279 #define DISPATCH(NAME,MAXSIZE)          \
280         MOVD    $MAXSIZE, R31;          \
281         CMP     R3, R31;                \
282         BGT     4(PC);                  \
283         MOVD    $NAME(SB), R31; \
284         MOVD    R31, CTR;               \
285         BR      (CTR)
286 // Note: can't just "BR NAME(SB)" - bad inlining results.
287
288 TEXT ·reflectcall(SB), NOSPLIT, $-8-24
289         MOVWZ n+16(FP), R3
290         DISPATCH(runtime·call16, 16)
291         DISPATCH(runtime·call32, 32)
292         DISPATCH(runtime·call64, 64)
293         DISPATCH(runtime·call128, 128)
294         DISPATCH(runtime·call256, 256)
295         DISPATCH(runtime·call512, 512)
296         DISPATCH(runtime·call1024, 1024)
297         DISPATCH(runtime·call2048, 2048)
298         DISPATCH(runtime·call4096, 4096)
299         DISPATCH(runtime·call8192, 8192)
300         DISPATCH(runtime·call16384, 16384)
301         DISPATCH(runtime·call32768, 32768)
302         DISPATCH(runtime·call65536, 65536)
303         DISPATCH(runtime·call131072, 131072)
304         DISPATCH(runtime·call262144, 262144)
305         DISPATCH(runtime·call524288, 524288)
306         DISPATCH(runtime·call1048576, 1048576)
307         DISPATCH(runtime·call2097152, 2097152)
308         DISPATCH(runtime·call4194304, 4194304)
309         DISPATCH(runtime·call8388608, 8388608)
310         DISPATCH(runtime·call16777216, 16777216)
311         DISPATCH(runtime·call33554432, 33554432)
312         DISPATCH(runtime·call67108864, 67108864)
313         DISPATCH(runtime·call134217728, 134217728)
314         DISPATCH(runtime·call268435456, 268435456)
315         DISPATCH(runtime·call536870912, 536870912)
316         DISPATCH(runtime·call1073741824, 1073741824)
317         MOVD    $runtime·badreflectcall(SB), R31
318         MOVD    R31, CTR
319         BR      (CTR)
320
321 #define CALLFN(NAME,MAXSIZE)                    \
322 TEXT NAME(SB), WRAPPER, $MAXSIZE-24;            \
323         NO_LOCAL_POINTERS;                      \
324         /* copy arguments to stack */           \
325         MOVD    arg+8(FP), R3;                  \
326         MOVWZ   n+16(FP), R4;                   \
327         MOVD    R1, R5;                         \
328         ADD     $(8-1), R5;                     \
329         SUB     $1, R3;                         \
330         ADD     R5, R4;                         \
331         CMP     R5, R4;                         \
332         BEQ     4(PC);                          \
333         MOVBZU  1(R3), R6;                      \
334         MOVBZU  R6, 1(R5);                      \
335         BR      -4(PC);                         \
336         /* call function */                     \
337         MOVD    f+0(FP), R11;                   \
338         MOVD    (R11), R31;                     \
339         MOVD    R31, CTR;                       \
340         PCDATA  $PCDATA_StackMapIndex, $0;      \
341         BL      (CTR);                          \
342         /* copy return values back */           \
343         MOVD    arg+8(FP), R3;                  \
344         MOVWZ   n+16(FP), R4;                   \
345         MOVWZ   retoffset+20(FP), R6;           \
346         MOVD    R1, R5;                         \
347         ADD     R6, R5;                         \
348         ADD     R6, R3;                         \
349         SUB     R6, R4;                         \
350         ADD     $(8-1), R5;                     \
351         SUB     $1, R3;                         \
352         ADD     R5, R4;                         \
353         CMP     R5, R4;                         \
354         BEQ     4(PC);                          \
355         MOVBZU  1(R5), R6;                      \
356         MOVBZU  R6, 1(R3);                      \
357         BR      -4(PC);                         \
358         RETURN
359
360 CALLFN(·call16, 16)
361 CALLFN(·call32, 32)
362 CALLFN(·call64, 64)
363 CALLFN(·call128, 128)
364 CALLFN(·call256, 256)
365 CALLFN(·call512, 512)
366 CALLFN(·call1024, 1024)
367 CALLFN(·call2048, 2048)
368 CALLFN(·call4096, 4096)
369 CALLFN(·call8192, 8192)
370 CALLFN(·call16384, 16384)
371 CALLFN(·call32768, 32768)
372 CALLFN(·call65536, 65536)
373 CALLFN(·call131072, 131072)
374 CALLFN(·call262144, 262144)
375 CALLFN(·call524288, 524288)
376 CALLFN(·call1048576, 1048576)
377 CALLFN(·call2097152, 2097152)
378 CALLFN(·call4194304, 4194304)
379 CALLFN(·call8388608, 8388608)
380 CALLFN(·call16777216, 16777216)
381 CALLFN(·call33554432, 33554432)
382 CALLFN(·call67108864, 67108864)
383 CALLFN(·call134217728, 134217728)
384 CALLFN(·call268435456, 268435456)
385 CALLFN(·call536870912, 536870912)
386 CALLFN(·call1073741824, 1073741824)
387
388 // bool cas(uint32 *ptr, uint32 old, uint32 new)
389 // Atomically:
390 //      if(*val == old){
391 //              *val = new;
392 //              return 1;
393 //      } else
394 //              return 0;
395 TEXT runtime·cas(SB), NOSPLIT, $0-17
396         MOVD    ptr+0(FP), R3
397         MOVWZ   old+8(FP), R4
398         MOVWZ   new+12(FP), R5
399 cas_again:
400         SYNC
401         LWAR    (R3), R6
402         CMPW    R6, R4
403         BNE     cas_fail
404         STWCCC  R5, (R3)
405         BNE     cas_again
406         MOVD    $1, R3
407         SYNC
408         ISYNC
409         MOVB    R3, ret+16(FP)
410         RETURN
411 cas_fail:
412         MOVD    $0, R3
413         BR      -5(PC)
414
415 // bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
416 // Atomically:
417 //      if(*val == *old){
418 //              *val = new;
419 //              return 1;
420 //      } else {
421 //              return 0;
422 //      }
423 TEXT runtime·cas64(SB), NOSPLIT, $0-25
424         MOVD    ptr+0(FP), R3
425         MOVD    old+8(FP), R4
426         MOVD    new+16(FP), R5
427 cas64_again:
428         SYNC
429         LDAR    (R3), R6
430         CMP     R6, R4
431         BNE     cas64_fail
432         STDCCC  R5, (R3)
433         BNE     cas64_again
434         MOVD    $1, R3
435         SYNC
436         ISYNC
437         MOVB    R3, ret+24(FP)
438         RETURN
439 cas64_fail:
440         MOVD    $0, R3
441         BR      -5(PC)
442
443 TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
444         BR      runtime·cas64(SB)
445
446 TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
447         BR      runtime·atomicload64(SB)
448
449 TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
450         BR      runtime·atomicload64(SB)
451
452 TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
453         BR      runtime·atomicstore64(SB)
454
455 // bool casp(void **val, void *old, void *new)
456 // Atomically:
457 //      if(*val == old){
458 //              *val = new;
459 //              return 1;
460 //      } else
461 //              return 0;
462 TEXT runtime·casp1(SB), NOSPLIT, $0-25
463         BR runtime·cas64(SB)
464
465 // uint32 xadd(uint32 volatile *ptr, int32 delta)
466 // Atomically:
467 //      *val += delta;
468 //      return *val;
469 TEXT runtime·xadd(SB), NOSPLIT, $0-20
470         MOVD    ptr+0(FP), R4
471         MOVW    delta+8(FP), R5
472         SYNC
473         LWAR    (R4), R3
474         ADD     R5, R3
475         STWCCC  R3, (R4)
476         BNE     -4(PC)
477         SYNC
478         ISYNC
479         MOVW    R3, ret+16(FP)
480         RETURN
481
482 TEXT runtime·xadd64(SB), NOSPLIT, $0-24
483         MOVD    ptr+0(FP), R4
484         MOVD    delta+8(FP), R5
485         SYNC
486         LDAR    (R4), R3
487         ADD     R5, R3
488         STDCCC  R3, (R4)
489         BNE     -4(PC)
490         SYNC
491         ISYNC
492         MOVD    R3, ret+16(FP)
493         RETURN
494
495 TEXT runtime·xchg(SB), NOSPLIT, $0-20
496         MOVD    ptr+0(FP), R4
497         MOVW    new+8(FP), R5
498         SYNC
499         LWAR    (R4), R3
500         STWCCC  R5, (R4)
501         BNE     -3(PC)
502         SYNC
503         ISYNC
504         MOVW    R3, ret+16(FP)
505         RETURN
506
507 TEXT runtime·xchg64(SB), NOSPLIT, $0-24
508         MOVD    ptr+0(FP), R4
509         MOVD    new+8(FP), R5
510         SYNC
511         LDAR    (R4), R3
512         STDCCC  R5, (R4)
513         BNE     -3(PC)
514         SYNC
515         ISYNC
516         MOVD    R3, ret+16(FP)
517         RETURN
518
519 TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
520         BR      runtime·xchg64(SB)
521
522 TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
523         BR      runtime·xchg64(SB)
524
525 TEXT runtime·procyield(SB),NOSPLIT,$0-0
526         RETURN
527
528 TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
529         BR      runtime·atomicstore64(SB)
530
531 TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
532         MOVD    ptr+0(FP), R3
533         MOVW    val+8(FP), R4
534         SYNC
535         MOVW    R4, 0(R3)
536         RETURN
537
538 TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
539         MOVD    ptr+0(FP), R3
540         MOVD    val+8(FP), R4
541         SYNC
542         MOVD    R4, 0(R3)
543         RETURN
544
545 // void runtime·atomicor8(byte volatile*, byte);
546 TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
547         MOVD    ptr+0(FP), R3
548         MOVBZ   val+8(FP), R4
549         // Align ptr down to 4 bytes so we can use 32-bit load/store.
550         // R5 = (R3 << 0) & ~3
551         RLDCR   $0, R3, $~3, R5
552         // Compute val shift.
553 #ifdef GOARCH_power64
554         // Big endian.  ptr = ptr ^ 3
555         XOR     $3, R3
556 #endif
557         // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
558         RLDC    $3, R3, $(3*8), R6
559         // Shift val for aligned ptr.  R4 = val << R6
560         SLD     R6, R4, R4
561
562 atomicor8_again:
563         SYNC
564         LWAR    (R5), R6
565         OR      R4, R6
566         STWCCC  R6, (R5)
567         BNE     atomicor8_again
568         SYNC
569         ISYNC
570         RETURN
571
572 // void jmpdefer(fv, sp);
573 // called from deferreturn.
574 // 1. grab stored LR for caller
575 // 2. sub 4 bytes to get back to BL deferreturn
576 // 3. BR to fn
577 TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
578         MOVD    0(R1), R31
579         SUB     $4, R31
580         MOVD    R31, LR
581
582         MOVD    fv+0(FP), R11
583         MOVD    argp+8(FP), R1
584         SUB     $8, R1
585         MOVD    0(R11), R3
586         MOVD    R3, CTR
587         BR      (CTR)
588
589 // Save state of caller into g->sched. Smashes R31.
590 TEXT gosave<>(SB),NOSPLIT,$-8
591         MOVD    LR, R31
592         MOVD    R31, (g_sched+gobuf_pc)(g)
593         MOVD    R1, (g_sched+gobuf_sp)(g)
594         MOVD    R0, (g_sched+gobuf_lr)(g)
595         MOVD    R0, (g_sched+gobuf_ret)(g)
596         MOVD    R0, (g_sched+gobuf_ctxt)(g)
597         RETURN
598
599 // asmcgocall(void(*fn)(void*), void *arg)
600 // Call fn(arg) on the scheduler stack,
601 // aligned appropriately for the gcc ABI.
602 // See cgocall.c for more details.
603 TEXT ·asmcgocall(SB),NOSPLIT,$0-16
604         MOVD    R0, 21(R0)
605
606 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
607 // Turn the fn into a Go func (by taking its address) and call
608 // cgocallback_gofunc.
609 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
610         MOVD    R0, 22(R0)
611
612 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
613 // See cgocall.c for more details.
614 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
615         MOVD    R0, 23(R0)
616
617 // void setg(G*); set g. for use by needm.
618 TEXT runtime·setg(SB), NOSPLIT, $0-8
619         MOVD    R0, 24(R0)
620
621 // void setg_gcc(G*); set g called from gcc.
622 TEXT setg_gcc<>(SB),NOSPLIT,$0
623         MOVD    R0, 25(R0)
624
625 TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16
626         MOVD    0(R1), R3
627         MOVD    R3, ret+8(FP)
628         RETURN
629
630 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
631         MOVD    0(R1), R3
632         MOVD    R3,ret+8(FP)
633         RETURN
634
635 TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
636         MOVD    pc+8(FP), R3
637         MOVD    R3, 0(R1)               // set calling pc
638         RETURN
639
640 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
641         MOVD    argp+0(FP), R3
642         SUB     $8, R3
643         MOVD    R3, ret+8(FP)
644         RETURN
645
646 // func gogetcallersp(p unsafe.Pointer) uintptr
647 TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
648         MOVD    sp+0(FP), R3
649         SUB     $8, R3
650         MOVD    R3,ret+8(FP)
651         RETURN
652
653 TEXT runtime·abort(SB),NOSPLIT,$-8-0
654         MOVW    (R0), R0
655         UNDEF
656
657 #define TBRL    268
658 #define TBRU    269             /* Time base Upper/Lower */
659
660 // int64 runtime·cputicks(void)
661 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
662         MOVW    SPR(TBRU), R4
663         MOVW    SPR(TBRL), R3
664         MOVW    SPR(TBRU), R5
665         CMPW    R4, R5
666         BNE     -4(PC)
667         SLD     $32, R5
668         OR      R5, R3
669         MOVD    R3, ret+0(FP)
670         RETURN
671
672 // AES hashing not implemented for Power
673 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
674         MOVW    (R0), R1
675 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
676         MOVW    (R0), R1
677 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
678         MOVW    (R0), R1
679 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
680         MOVW    (R0), R1
681
682 TEXT runtime·memeq(SB),NOSPLIT,$-8-25
683         MOVD    a+0(FP), R3
684         MOVD    b+8(FP), R4
685         MOVD    size+16(FP), R5
686         SUB     $1, R3
687         SUB     $1, R4
688         ADD     R3, R5, R8
689 loop:
690         CMP     R3, R8
691         BNE     test
692         MOVD    $1, R3
693         MOVB    R3, ret+24(FP)
694         RETURN
695 test:
696         MOVBZU  1(R3), R6
697         MOVBZU  1(R4), R7
698         CMP     R6, R7
699         BEQ     loop
700
701         MOVB    R0, ret+24(FP)
702         RETURN
703
704 // eqstring tests whether two strings are equal.
705 // See runtime_test.go:eqstring_generic for
706 // equivalent Go code.
707 TEXT runtime·eqstring(SB),NOSPLIT,$0-33
708         MOVD    s1len+8(FP), R4
709         MOVD    s2len+24(FP), R5
710         CMP     R4, R5
711         BNE     noteq
712
713         MOVD    s1str+0(FP), R3
714         MOVD    s2str+16(FP), R4
715         SUB     $1, R3
716         SUB     $1, R4
717         ADD     R3, R5, R8
718 loop:
719         CMP     R3, R8
720         BNE     4(PC)
721         MOVD    $1, R3
722         MOVB    R3, ret+32(FP)
723         RETURN
724         MOVBZU  1(R3), R6
725         MOVBZU  1(R4), R7
726         CMP     R6, R7
727         BEQ     loop
728 noteq:
729         MOVB    R0, ret+32(FP)
730         RETURN
731
732 // TODO: share code with memeq?
733 TEXT bytes·Equal(SB),NOSPLIT,$0-49
734         MOVD    a_len+8(FP), R3
735         MOVD    b_len+32(FP), R4
736
737         CMP     R3, R4          // unequal lengths are not equal
738         BNE     noteq
739
740         MOVD    a+0(FP), R5
741         MOVD    b+24(FP), R6
742         SUB     $1, R5
743         SUB     $1, R6
744         ADD     R5, R3          // end-1
745
746 loop:
747         CMP     R5, R3
748         BEQ     equal           // reached the end
749         MOVBZU  1(R5), R4
750         MOVBZU  1(R6), R7
751         CMP     R4, R7
752         BEQ     loop
753
754 noteq:
755         MOVBZ   R0, ret+48(FP)
756         RETURN
757
758 equal:
759         MOVD    $1, R3
760         MOVBZ   R3, ret+48(FP)
761         RETURN
762
763 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
764         MOVD    s+0(FP), R3
765         MOVD    s_len+8(FP), R4
766         MOVBZ   c+24(FP), R5    // byte to find
767         MOVD    R3, R6          // store base for later
768         SUB     $1, R3
769         ADD     R3, R4          // end-1
770
771 loop:
772         CMP     R3, R4
773         BEQ     notfound
774         MOVBZU  1(R3), R7
775         CMP     R7, R5
776         BNE     loop
777
778         SUB     R6, R3          // remove base
779         MOVD    R3, ret+32(FP)
780         RETURN
781
782 notfound:
783         MOVD    $-1, R3
784         MOVD    R3, ret+32(FP)
785         RETURN
786
787 TEXT strings·IndexByte(SB),NOSPLIT,$0
788         MOVD    p+0(FP), R3
789         MOVD    b_len+8(FP), R4
790         MOVBZ   c+16(FP), R5    // byte to find
791         MOVD    R3, R6          // store base for later
792         SUB     $1, R3
793         ADD     R3, R4          // end-1
794
795 loop:
796         CMP     R3, R4
797         BEQ     notfound
798         MOVBZU  1(R3), R7
799         CMP     R7, R5
800         BNE     loop
801
802         SUB     R6, R3          // remove base
803         MOVD    R3, ret+24(FP)
804         RETURN
805
806 notfound:
807         MOVD    $-1, R3
808         MOVD    R3, ret+24(FP)
809         RETURN
810
811
812 // A Duff's device for zeroing memory.
813 // The compiler jumps to computed addresses within
814 // this routine to zero chunks of memory.  Do not
815 // change this code without also changing the code
816 // in ../../cmd/9g/ggen.c:/^clearfat.
817 // R0: always zero
818 // R3 (aka REGRT1): ptr to memory to be zeroed - 8
819 // On return, R3 points to the last zeroed dword.
820 TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
821         MOVDU   R0, 8(R3)
822         MOVDU   R0, 8(R3)
823         MOVDU   R0, 8(R3)
824         MOVDU   R0, 8(R3)
825         MOVDU   R0, 8(R3)
826         MOVDU   R0, 8(R3)
827         MOVDU   R0, 8(R3)
828         MOVDU   R0, 8(R3)
829         MOVDU   R0, 8(R3)
830         MOVDU   R0, 8(R3)
831         MOVDU   R0, 8(R3)
832         MOVDU   R0, 8(R3)
833         MOVDU   R0, 8(R3)
834         MOVDU   R0, 8(R3)
835         MOVDU   R0, 8(R3)
836         MOVDU   R0, 8(R3)
837         MOVDU   R0, 8(R3)
838         MOVDU   R0, 8(R3)
839         MOVDU   R0, 8(R3)
840         MOVDU   R0, 8(R3)
841         MOVDU   R0, 8(R3)
842         MOVDU   R0, 8(R3)
843         MOVDU   R0, 8(R3)
844         MOVDU   R0, 8(R3)
845         MOVDU   R0, 8(R3)
846         MOVDU   R0, 8(R3)
847         MOVDU   R0, 8(R3)
848         MOVDU   R0, 8(R3)
849         MOVDU   R0, 8(R3)
850         MOVDU   R0, 8(R3)
851         MOVDU   R0, 8(R3)
852         MOVDU   R0, 8(R3)
853         MOVDU   R0, 8(R3)
854         MOVDU   R0, 8(R3)
855         MOVDU   R0, 8(R3)
856         MOVDU   R0, 8(R3)
857         MOVDU   R0, 8(R3)
858         MOVDU   R0, 8(R3)
859         MOVDU   R0, 8(R3)
860         MOVDU   R0, 8(R3)
861         MOVDU   R0, 8(R3)
862         MOVDU   R0, 8(R3)
863         MOVDU   R0, 8(R3)
864         MOVDU   R0, 8(R3)
865         MOVDU   R0, 8(R3)
866         MOVDU   R0, 8(R3)
867         MOVDU   R0, 8(R3)
868         MOVDU   R0, 8(R3)
869         MOVDU   R0, 8(R3)
870         MOVDU   R0, 8(R3)
871         MOVDU   R0, 8(R3)
872         MOVDU   R0, 8(R3)
873         MOVDU   R0, 8(R3)
874         MOVDU   R0, 8(R3)
875         MOVDU   R0, 8(R3)
876         MOVDU   R0, 8(R3)
877         MOVDU   R0, 8(R3)
878         MOVDU   R0, 8(R3)
879         MOVDU   R0, 8(R3)
880         MOVDU   R0, 8(R3)
881         MOVDU   R0, 8(R3)
882         MOVDU   R0, 8(R3)
883         MOVDU   R0, 8(R3)
884         MOVDU   R0, 8(R3)
885         MOVDU   R0, 8(R3)
886         MOVDU   R0, 8(R3)
887         MOVDU   R0, 8(R3)
888         MOVDU   R0, 8(R3)
889         MOVDU   R0, 8(R3)
890         MOVDU   R0, 8(R3)
891         MOVDU   R0, 8(R3)
892         MOVDU   R0, 8(R3)
893         MOVDU   R0, 8(R3)
894         MOVDU   R0, 8(R3)
895         MOVDU   R0, 8(R3)
896         MOVDU   R0, 8(R3)
897         MOVDU   R0, 8(R3)
898         MOVDU   R0, 8(R3)
899         MOVDU   R0, 8(R3)
900         MOVDU   R0, 8(R3)
901         MOVDU   R0, 8(R3)
902         MOVDU   R0, 8(R3)
903         MOVDU   R0, 8(R3)
904         MOVDU   R0, 8(R3)
905         MOVDU   R0, 8(R3)
906         MOVDU   R0, 8(R3)
907         MOVDU   R0, 8(R3)
908         MOVDU   R0, 8(R3)
909         MOVDU   R0, 8(R3)
910         MOVDU   R0, 8(R3)
911         MOVDU   R0, 8(R3)
912         MOVDU   R0, 8(R3)
913         MOVDU   R0, 8(R3)
914         MOVDU   R0, 8(R3)
915         MOVDU   R0, 8(R3)
916         MOVDU   R0, 8(R3)
917         MOVDU   R0, 8(R3)
918         MOVDU   R0, 8(R3)
919         MOVDU   R0, 8(R3)
920         MOVDU   R0, 8(R3)
921         MOVDU   R0, 8(R3)
922         MOVDU   R0, 8(R3)
923         MOVDU   R0, 8(R3)
924         MOVDU   R0, 8(R3)
925         MOVDU   R0, 8(R3)
926         MOVDU   R0, 8(R3)
927         MOVDU   R0, 8(R3)
928         MOVDU   R0, 8(R3)
929         MOVDU   R0, 8(R3)
930         MOVDU   R0, 8(R3)
931         MOVDU   R0, 8(R3)
932         MOVDU   R0, 8(R3)
933         MOVDU   R0, 8(R3)
934         MOVDU   R0, 8(R3)
935         MOVDU   R0, 8(R3)
936         MOVDU   R0, 8(R3)
937         MOVDU   R0, 8(R3)
938         MOVDU   R0, 8(R3)
939         MOVDU   R0, 8(R3)
940         MOVDU   R0, 8(R3)
941         MOVDU   R0, 8(R3)
942         MOVDU   R0, 8(R3)
943         MOVDU   R0, 8(R3)
944         MOVDU   R0, 8(R3)
945         MOVDU   R0, 8(R3)
946         MOVDU   R0, 8(R3)
947         MOVDU   R0, 8(R3)
948         MOVDU   R0, 8(R3)
949         RETURN
950
951 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
952         MOVD    g_m(g), R4
953         MOVWZ   m_fastrand(R4), R3
954         ADD     R3, R3
955         CMPW    R3, $0
956         BGE     2(PC)
957         XOR     $0x88888eef, R3
958         MOVW    R3, m_fastrand(R4)
959         MOVW    R3, ret+0(FP)
960         RETURN
961
962 TEXT runtime·return0(SB), NOSPLIT, $0
963         MOVW    $0, R3
964         RETURN
965
966 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
967 // Must obey the gcc calling convention.
968 TEXT _cgo_topofstack(SB),NOSPLIT,$0
969         MOVD    R0, 26(R0)
970
971 // The top-most function running on a goroutine
972 // returns to goexit+PCQuantum.
973 TEXT runtime·goexit(SB),NOSPLIT,$-8-0
974         MOVD    R0, R0  // NOP
975         BL      runtime·goexit1(SB)    // does not return
976
977 TEXT runtime·getg(SB),NOSPLIT,$-8-8
978         MOVD    g, ret+0(FP)
979         RETURN