Text file src/runtime/race_ppc64le.s
1 // Copyright 2018 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 race
6
7 #include "go_asm.h"
8 #include "go_tls.h"
9 #include "funcdata.h"
10 #include "textflag.h"
11
12 // The following functions allow calling the clang-compiled race runtime directly
13 // from Go code without going all the way through cgo.
14 // First, it's much faster (up to 50% speedup for real Go programs).
15 // Second, it eliminates race-related special cases from cgocall and scheduler.
16 // Third, in long-term it will allow to remove cyclic runtime/race dependency on cmd/go.
17
18 // A brief recap of the ppc64le calling convention.
19 // Arguments are passed in R3, R4, R5 ...
20 // SP must be 16-byte aligned.
21
22 // Note that for ppc64x, LLVM follows the standard ABI and
23 // expects arguments in registers, so these functions move
24 // the arguments from storage to the registers expected
25 // by the ABI.
26
27 // When calling from Go to Clang tsan code:
28 // R3 is the 1st argument and is usually the ThreadState*
29 // R4-? are the 2nd, 3rd, 4th, etc. arguments
30
31 // When calling racecalladdr:
32 // R8 is the call target address
33
34 // The race ctx is passed in R3 and loaded in
35 // racecalladdr.
36 //
37 // The sequence used to get the race ctx:
38 // MOVD runtime·tls_g(SB), R10 // offset to TLS
39 // MOVD 0(R13)(R10*1), g // R13=TLS for this thread, g = R30
40 // MOVD g_racectx(g), R3 // racectx == ThreadState
41
42 // func runtime·RaceRead(addr uintptr)
43 // Called from instrumented Go code
44 TEXT runtime·raceread(SB), NOSPLIT, $0-8
45 MOVD addr+0(FP), R4
46 MOVD LR, R5 // caller of this?
47 // void __tsan_read(ThreadState *thr, void *addr, void *pc);
48 MOVD $__tsan_read(SB), R8
49 BR racecalladdr<>(SB)
50
51 TEXT runtime·RaceRead(SB), NOSPLIT, $0-8
52 BR runtime·raceread(SB)
53
54 // void runtime·racereadpc(void *addr, void *callpc, void *pc)
55 TEXT runtime·racereadpc(SB), NOSPLIT, $0-24
56 MOVD addr+0(FP), R4
57 MOVD callpc+8(FP), R5
58 MOVD pc+16(FP), R6
59 // void __tsan_read_pc(ThreadState *thr, void *addr, void *callpc, void *pc);
60 MOVD $__tsan_read_pc(SB), R8
61 BR racecalladdr<>(SB)
62
63 // func runtime·RaceWrite(addr uintptr)
64 // Called from instrumented Go code
65 TEXT runtime·racewrite(SB), NOSPLIT, $0-8
66 MOVD addr+0(FP), R4
67 MOVD LR, R5 // caller has set LR via BL inst
68 // void __tsan_write(ThreadState *thr, void *addr, void *pc);
69 MOVD $__tsan_write(SB), R8
70 BR racecalladdr<>(SB)
71
72 TEXT runtime·RaceWrite(SB), NOSPLIT, $0-8
73 JMP runtime·racewrite(SB)
74
75 // void runtime·racewritepc(void *addr, void *callpc, void *pc)
76 TEXT runtime·racewritepc(SB), NOSPLIT, $0-24
77 MOVD addr+0(FP), R4
78 MOVD callpc+8(FP), R5
79 MOVD pc+16(FP), R6
80 // void __tsan_write_pc(ThreadState *thr, void *addr, void *callpc, void *pc);
81 MOVD $__tsan_write_pc(SB), R8
82 BR racecalladdr<>(SB)
83
84 // func runtime·RaceReadRange(addr, size uintptr)
85 // Called from instrumented Go code.
86 TEXT runtime·racereadrange(SB), NOSPLIT, $0-16
87 MOVD addr+0(FP), R4
88 MOVD size+8(FP), R5
89 MOVD LR, R6
90 // void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc);
91 MOVD $__tsan_read_range(SB), R8
92 BR racecalladdr<>(SB)
93
94 // void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc)
95 TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24
96 MOVD addr+0(FP), R4
97 MOVD size+8(FP), R5
98 MOVD pc+16(FP), R6
99 ADD $4, R6 // tsan wants return addr
100 // void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc);
101 MOVD $__tsan_read_range(SB), R8
102 BR racecalladdr<>(SB)
103
104 TEXT runtime·RaceReadRange(SB), NOSPLIT, $0-24
105 BR runtime·racereadrange(SB)
106
107 // func runtime·RaceWriteRange(addr, size uintptr)
108 // Called from instrumented Go code.
109 TEXT runtime·racewriterange(SB), NOSPLIT, $0-16
110 MOVD addr+0(FP), R4
111 MOVD size+8(FP), R5
112 MOVD LR, R6
113 // void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc);
114 MOVD $__tsan_write_range(SB), R8
115 BR racecalladdr<>(SB)
116
117 TEXT runtime·RaceWriteRange(SB), NOSPLIT, $0-16
118 BR runtime·racewriterange(SB)
119
120 // void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc)
121 // Called from instrumented Go code
122 TEXT runtime·racewriterangepc1(SB), NOSPLIT, $0-24
123 MOVD addr+0(FP), R4
124 MOVD size+8(FP), R5
125 MOVD pc+16(FP), R6
126 ADD $4, R6 // add 4 to inst offset?
127 // void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc);
128 MOVD $__tsan_write_range(SB), R8
129 BR racecalladdr<>(SB)
130
131 // Call a __tsan function from Go code.
132 // R8 = tsan function address
133 // R3 = *ThreadState a.k.a. g_racectx from g
134 // R4 = addr passed to __tsan function
135 //
136 // Otherwise, setup goroutine context and invoke racecall. Other arguments already set.
137 TEXT racecalladdr<>(SB), NOSPLIT, $0-0
138 MOVD runtime·tls_g(SB), R10
139 MOVD 0(R13)(R10*1), g
140 MOVD g_racectx(g), R3 // goroutine context
141 // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
142 MOVD runtime·racearenastart(SB), R9
143 CMP R4, R9
144 BLT data
145 MOVD runtime·racearenaend(SB), R9
146 CMP R4, R9
147 BLT call
148 data:
149 MOVD runtime·racedatastart(SB), R9
150 CMP R4, R9
151 BLT ret
152 MOVD runtime·racedataend(SB), R9
153 CMP R4, R9
154 BGT ret
155 call:
156 // Careful!! racecall will save LR on its
157 // stack, which is OK as long as racecalladdr
158 // doesn't change in a way that generates a stack.
159 // racecall should return to the caller of
160 // recalladdr.
161 BR racecall<>(SB)
162 ret:
163 RET
164
165 // func runtime·racefuncenterfp()
166 // Called from instrumented Go code.
167 // Like racefuncenter but doesn't pass an arg, uses the caller pc
168 // from the first slot on the stack.
169 TEXT runtime·racefuncenterfp(SB), NOSPLIT, $0-0
170 MOVD 0(R1), R8
171 BR racefuncenter<>(SB)
172
173 // func runtime·racefuncenter(pc uintptr)
174 // Called from instrumented Go code.
175 // Not used now since gc/racewalk.go doesn't pass the
176 // correct caller pc and racefuncenterfp can do it.
177 TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
178 MOVD callpc+0(FP), R8
179 BR racefuncenter<>(SB)
180
181 // Common code for racefuncenter/racefuncenterfp
182 // R11 = caller's return address
183 TEXT racefuncenter<>(SB), NOSPLIT, $0-0
184 MOVD runtime·tls_g(SB), R10
185 MOVD 0(R13)(R10*1), g
186 MOVD g_racectx(g), R3 // goroutine racectx aka *ThreadState
187 MOVD R8, R4 // caller pc set by caller in R8
188 // void __tsan_func_enter(ThreadState *thr, void *pc);
189 MOVD $__tsan_func_enter(SB), R8
190 BR racecall<>(SB)
191 RET
192
193 // func runtime·racefuncexit()
194 // Called from Go instrumented code.
195 TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0
196 MOVD runtime·tls_g(SB), R10
197 MOVD 0(R13)(R10*1), g
198 MOVD g_racectx(g), R3 // goroutine racectx aka *ThreadState
199 // void __tsan_func_exit(ThreadState *thr);
200 MOVD $__tsan_func_exit(SB), R8
201 BR racecall<>(SB)
202
203 // Atomic operations for sync/atomic package.
204 // Some use the __tsan versions instead
205 // R6 = addr of arguments passed to this function
206 // R3, R4, R5 set in racecallatomic
207
208 // Load atomic in tsan
209 TEXT sync∕atomic·LoadInt32(SB), NOSPLIT, $0-0
210 // void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
211 MOVD $__tsan_go_atomic32_load(SB), R8
212 ADD $32, R1, R6 // addr of caller's 1st arg
213 BR racecallatomic<>(SB)
214 RET
215
216 TEXT sync∕atomic·LoadInt64(SB), NOSPLIT, $0-0
217 // void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
218 MOVD $__tsan_go_atomic64_load(SB), R8
219 ADD $32, R1, R6 // addr of caller's 1st arg
220 BR racecallatomic<>(SB)
221 RET
222
223 TEXT sync∕atomic·LoadUint32(SB), NOSPLIT, $0-0
224 BR sync∕atomic·LoadInt32(SB)
225
226 TEXT sync∕atomic·LoadUint64(SB), NOSPLIT, $0-0
227 BR sync∕atomic·LoadInt64(SB)
228
229 TEXT sync∕atomic·LoadUintptr(SB), NOSPLIT, $0-0
230 BR sync∕atomic·LoadInt64(SB)
231
232 TEXT sync∕atomic·LoadPointer(SB), NOSPLIT, $0-0
233 BR sync∕atomic·LoadInt64(SB)
234
235 // Store atomic in tsan
236 TEXT sync∕atomic·StoreInt32(SB), NOSPLIT, $0-0
237 // void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
238 MOVD $__tsan_go_atomic32_store(SB), R8
239 ADD $32, R1, R6 // addr of caller's 1st arg
240 BR racecallatomic<>(SB)
241
242 TEXT sync∕atomic·StoreInt64(SB), NOSPLIT, $0-0
243 // void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
244 MOVD $__tsan_go_atomic64_store(SB), R8
245 ADD $32, R1, R6 // addr of caller's 1st arg
246 BR racecallatomic<>(SB)
247
248 TEXT sync∕atomic·StoreUint32(SB), NOSPLIT, $0-0
249 BR sync∕atomic·StoreInt32(SB)
250
251 TEXT sync∕atomic·StoreUint64(SB), NOSPLIT, $0-0
252 BR sync∕atomic·StoreInt64(SB)
253
254 TEXT sync∕atomic·StoreUintptr(SB), NOSPLIT, $0-0
255 BR sync∕atomic·StoreInt64(SB)
256
257 // Swap in tsan
258 TEXT sync∕atomic·SwapInt32(SB), NOSPLIT, $0-0
259 // void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
260 MOVD $__tsan_go_atomic32_exchange(SB), R8
261 ADD $32, R1, R6 // addr of caller's 1st arg
262 BR racecallatomic<>(SB)
263
264 TEXT sync∕atomic·SwapInt64(SB), NOSPLIT, $0-0
265 // void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a)
266 MOVD $__tsan_go_atomic64_exchange(SB), R8
267 ADD $32, R1, R6 // addr of caller's 1st arg
268 BR racecallatomic<>(SB)
269
270 TEXT sync∕atomic·SwapUint32(SB), NOSPLIT, $0-0
271 BR sync∕atomic·SwapInt32(SB)
272
273 TEXT sync∕atomic·SwapUint64(SB), NOSPLIT, $0-0
274 BR sync∕atomic·SwapInt64(SB)
275
276 TEXT sync∕atomic·SwapUintptr(SB), NOSPLIT, $0-0
277 BR sync∕atomic·SwapInt64(SB)
278
279 // Add atomic in tsan
280 TEXT sync∕atomic·AddInt32(SB), NOSPLIT, $0-0
281 // void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
282 MOVD $__tsan_go_atomic32_fetch_add(SB), R8
283 ADD $64, R1, R6 // addr of caller's 1st arg
284 BL racecallatomic<>(SB)
285 // The tsan fetch_add result is not as expected by Go,
286 // so the 'add' must be added to the result.
287 MOVW add+8(FP), R3 // The tsa fetch_add does not return the
288 MOVW ret+16(FP), R4 // result as expected by go, so fix it.
289 ADD R3, R4, R3
290 MOVW R3, ret+16(FP)
291 RET
292
293 TEXT sync∕atomic·AddInt64(SB), NOSPLIT, $0-0
294 // void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
295 MOVD $__tsan_go_atomic64_fetch_add(SB), R8
296 ADD $64, R1, R6 // addr of caller's 1st arg
297 BL racecallatomic<>(SB)
298 // The tsan fetch_add result is not as expected by Go,
299 // so the 'add' must be added to the result.
300 MOVD add+8(FP), R3
301 MOVD ret+16(FP), R4
302 ADD R3, R4, R3
303 MOVD R3, ret+16(FP)
304 RET
305
306 TEXT sync∕atomic·AddUint32(SB), NOSPLIT, $0-0
307 BR sync∕atomic·AddInt32(SB)
308
309 TEXT sync∕atomic·AddUint64(SB), NOSPLIT, $0-0
310 BR sync∕atomic·AddInt64(SB)
311
312 TEXT sync∕atomic·AddUintptr(SB), NOSPLIT, $0-0
313 BR sync∕atomic·AddInt64(SB)
314
315 // CompareAndSwap in tsan
316 TEXT sync∕atomic·CompareAndSwapInt32(SB), NOSPLIT, $0-0
317 // void __tsan_go_atomic32_compare_exchange(
318 // ThreadState *thr, uptr cpc, uptr pc, u8 *a)
319 MOVD $__tsan_go_atomic32_compare_exchange(SB), R8
320 ADD $32, R1, R6 // addr of caller's 1st arg
321 BR racecallatomic<>(SB)
322
323 TEXT sync∕atomic·CompareAndSwapInt64(SB), NOSPLIT, $0-0
324 // void __tsan_go_atomic32_compare_exchange(
325 // ThreadState *thr, uptr cpc, uptr pc, u8 *a)
326 MOVD $__tsan_go_atomic64_compare_exchange(SB), R8
327 ADD $32, R1, R6 // addr of caller's 1st arg
328 BR racecallatomic<>(SB)
329
330 TEXT sync∕atomic·CompareAndSwapUint32(SB), NOSPLIT, $0-0
331 BR sync∕atomic·CompareAndSwapInt32(SB)
332
333 TEXT sync∕atomic·CompareAndSwapUint64(SB), NOSPLIT, $0-0
334 BR sync∕atomic·CompareAndSwapInt64(SB)
335
336 TEXT sync∕atomic·CompareAndSwapUintptr(SB), NOSPLIT, $0-0
337 BR sync∕atomic·CompareAndSwapInt64(SB)
338
339 // Common function used to call tsan's atomic functions
340 // R3 = *ThreadState
341 // R4 = TODO: What's this supposed to be?
342 // R5 = caller pc
343 // R6 = addr of incoming arg list
344 // R8 contains addr of target function.
345 TEXT racecallatomic<>(SB), NOSPLIT, $0-0
346 // Trigger SIGSEGV early if address passed to atomic function is bad.
347 MOVD (R6), R7 // 1st arg is addr
348 MOVD (R7), R9 // segv here if addr is bad
349 // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
350 MOVD runtime·racearenastart(SB), R9
351 CMP R7, R9
352 BLT racecallatomic_data
353 MOVD runtime·racearenaend(SB), R9
354 CMP R7, R9
355 BLT racecallatomic_ok
356 racecallatomic_data:
357 MOVD runtime·racedatastart(SB), R9
358 CMP R7, R9
359 BLT racecallatomic_ignore
360 MOVD runtime·racedataend(SB), R9
361 CMP R7, R9
362 BGE racecallatomic_ignore
363 racecallatomic_ok:
364 // Addr is within the good range, call the atomic function.
365 MOVD runtime·tls_g(SB), R10
366 MOVD 0(R13)(R10*1), g
367 MOVD g_racectx(g), R3 // goroutine racectx aka *ThreadState
368 MOVD R8, R5 // pc is the function called
369 MOVD (R1), R4 // caller pc from stack
370 BL racecall<>(SB) // BL needed to maintain stack consistency
371 RET //
372 racecallatomic_ignore:
373 // Addr is outside the good range.
374 // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
375 // An attempt to synchronize on the address would cause crash.
376 MOVD R8, R15 // save the original function
377 MOVD R6, R17 // save the original arg list addr
378 MOVD $__tsan_go_ignore_sync_begin(SB), R8 // func addr to call
379 MOVD runtime·tls_g(SB), R10
380 MOVD 0(R13)(R10*1), g
381 MOVD g_racectx(g), R3 // goroutine context
382 BL racecall<>(SB)
383 MOVD R15, R8 // restore the original function
384 MOVD R17, R6 // restore arg list addr
385 // Call the atomic function.
386 // racecall will call LLVM race code which might clobber r30 (g)
387 MOVD runtime·tls_g(SB), R10
388 MOVD 0(R13)(R10*1), g
389
390 MOVD g_racectx(g), R3
391 MOVD R8, R4 // pc being called same TODO as above
392 MOVD (R1), R5 // caller pc from latest LR
393 BL racecall<>(SB)
394 // Call __tsan_go_ignore_sync_end.
395 MOVD $__tsan_go_ignore_sync_end(SB), R8
396 MOVD g_racectx(g), R3 // goroutine context g should sitll be good?
397 BL racecall<>(SB)
398 RET
399
400 // void runtime·racecall(void(*f)(...), ...)
401 // Calls C function f from race runtime and passes up to 4 arguments to it.
402 // The arguments are never heap-object-preserving pointers, so we pretend there are no arguments.
403 TEXT runtime·racecall(SB), NOSPLIT, $0-0
404 MOVD fn+0(FP), R8
405 MOVD arg0+8(FP), R3
406 MOVD arg1+16(FP), R4
407 MOVD arg2+24(FP), R5
408 MOVD arg3+32(FP), R6
409 JMP racecall<>(SB)
410
411 // Finds g0 and sets its stack
412 // Arguments were loaded for call from Go to C
413 TEXT racecall<>(SB), NOSPLIT, $0-0
414 // Set the LR slot for the ppc64 ABI
415 MOVD LR, R10
416 MOVD R10, 0(R1) // Go expectation
417 MOVD R10, 16(R1) // C ABI
418 // Get info from the current goroutine
419 MOVD runtime·tls_g(SB), R10 // g offset in TLS
420 MOVD 0(R13)(R10*1), g // R13 = current TLS
421 MOVD g_m(g), R7 // m for g
422 MOVD R1, R16 // callee-saved, preserved across C call
423 MOVD m_g0(R7), R10 // g0 for m
424 CMP R10, g // same g0?
425 BEQ call // already on g0
426 MOVD (g_sched+gobuf_sp)(R10), R1 // switch R1
427 call:
428 MOVD R8, CTR // R8 = caller addr
429 MOVD R8, R12 // expected by PPC64 ABI
430 BL (CTR)
431 XOR R0, R0 // clear R0 on return from Clang
432 MOVD R16, R1 // restore R1; R16 nonvol in Clang
433 MOVD runtime·tls_g(SB), R10 // find correct g
434 MOVD 0(R13)(R10*1), g
435 MOVD 16(R1), R10 // LR was saved away, restore for return
436 MOVD R10, LR
437 RET
438
439 // C->Go callback thunk that allows to call runtime·racesymbolize from C code.
440 // Direct Go->C race call has only switched SP, finish g->g0 switch by setting correct g.
441 // The overall effect of Go->C->Go call chain is similar to that of mcall.
442 // RARG0 contains command code. RARG1 contains command-specific context.
443 // See racecallback for command codes.
444 TEXT runtime·racecallbackthunk(SB), NOSPLIT, $-8
445 // Handle command raceGetProcCmd (0) here.
446 // First, code below assumes that we are on curg, while raceGetProcCmd
447 // can be executed on g0. Second, it is called frequently, so will
448 // benefit from this fast path.
449 XOR R0, R0 // clear R0 since we came from C code
450 CMP R3, $0
451 BNE rest
452 // g0 TODO: Don't modify g here since R30 is nonvolatile
453 MOVD g, R9
454 MOVD runtime·tls_g(SB), R10
455 MOVD 0(R13)(R10*1), g
456 MOVD g_m(g), R3
457 MOVD m_p(R3), R3
458 MOVD p_raceprocctx(R3), R3
459 MOVD R3, (R4)
460 MOVD R9, g // restore R30 ??
461 RET
462
463 // This is all similar to what cgo does
464 // Save registers according to the ppc64 ABI
465 rest:
466 MOVD LR, R10 // save link register
467 MOVD R10, 16(R1)
468 MOVW CR, R10
469 MOVW R10, 8(R1)
470 MOVDU R1, -336(R1) // Allocate frame needed for register save area
471
472 MOVD R14, 40(R1)
473 MOVD R15, 48(R1)
474 MOVD R16, 56(R1)
475 MOVD R17, 64(R1)
476 MOVD R18, 72(R1)
477 MOVD R19, 80(R1)
478 MOVD R20, 88(R1)
479 MOVD R21, 96(R1)
480 MOVD R22, 104(R1)
481 MOVD R23, 112(R1)
482 MOVD R24, 120(R1)
483 MOVD R25, 128(R1)
484 MOVD R26, 136(R1)
485 MOVD R27, 144(R1)
486 MOVD R28, 152(R1)
487 MOVD R29, 160(R1)
488 MOVD g, 168(R1) // R30
489 MOVD R31, 176(R1)
490 FMOVD F14, 184(R1)
491 FMOVD F15, 192(R1)
492 FMOVD F16, 200(R1)
493 FMOVD F17, 208(R1)
494 FMOVD F18, 216(R1)
495 FMOVD F19, 224(R1)
496 FMOVD F20, 232(R1)
497 FMOVD F21, 240(R1)
498 FMOVD F22, 248(R1)
499 FMOVD F23, 256(R1)
500 FMOVD F24, 264(R1)
501 FMOVD F25, 272(R1)
502 FMOVD F26, 280(R1)
503 FMOVD F27, 288(R1)
504 FMOVD F28, 296(R1)
505 FMOVD F29, 304(R1)
506 FMOVD F30, 312(R1)
507 FMOVD F31, 320(R1)
508
509 MOVD runtime·tls_g(SB), R10
510 MOVD 0(R13)(R10*1), g
511
512 MOVD g_m(g), R7
513 MOVD m_g0(R7), g // set g = m-> g0
514 MOVD R3, cmd+0(FP) // can't use R1 here ?? use input args and assumer caller expects those?
515 MOVD R4, ctx+8(FP) // can't use R1 here ??
516 BL runtime·racecallback(SB)
517 // All registers are clobbered after Go code, reload.
518 MOVD runtime·tls_g(SB), R10
519 MOVD 0(R13)(R10*1), g
520
521 MOVD g_m(g), R7
522 MOVD m_curg(R7), g // restore g = m->curg
523 MOVD 40(R1), R14
524 MOVD 48(R1), R15
525 MOVD 56(R1), R16
526 MOVD 64(R1), R17
527 MOVD 72(R1), R18
528 MOVD 80(R1), R19
529 MOVD 88(R1), R20
530 MOVD 96(R1), R21
531 MOVD 104(R1), R22
532 MOVD 112(R1), R23
533 MOVD 120(R1), R24
534 MOVD 128(R1), R25
535 MOVD 136(R1), R26
536 MOVD 144(R1), R27
537 MOVD 152(R1), R28
538 MOVD 160(R1), R29
539 MOVD 168(R1), g // R30
540 MOVD 176(R1), R31
541 FMOVD 184(R1), F14
542 FMOVD 192(R1), F15
543 FMOVD 200(R1), F16
544 FMOVD 208(R1), F17
545 FMOVD 216(R1), F18
546 FMOVD 224(R1), F19
547 FMOVD 232(R1), F20
548 FMOVD 240(R1), F21
549 FMOVD 248(R1), F22
550 FMOVD 256(R1), F23
551 FMOVD 264(R1), F24
552 FMOVD 272(R1), F25
553 FMOVD 280(R1), F26
554 FMOVD 288(R1), F27
555 FMOVD 296(R1), F28
556 FMOVD 304(R1), F29
557 FMOVD 312(R1), F30
558 FMOVD 320(R1), F31
559
560 ADD $336, R1
561 MOVD 8(R1), R10
562 MOVFL R10, $0xff // Restore of CR
563 MOVD 16(R1), R10 // needed?
564 MOVD R10, LR
565 RET
566
567 // tls_g, g value for each thread in TLS
568 GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
View as plain text