github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/runtime/race_ppc64le.s (about)

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