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