// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "textflag.h"

// xx_cgo_panicmem is the entrypoint for SIGSEGV as intercepted via a
// mach thread port as EXC_BAD_ACCESS. As the segfault may have happened
// in C code, we first need to load_g then call xx_cgo_panicmem.
//
//	R1 - LR at moment of fault
//	R2 - PC at moment of fault
TEXT xx_cgo_panicmem(SB),NOSPLIT,$-4
	// If in external C code, we need to load the g register.
	BL  runtime·load_g(SB)
	CMP $0, g
	BNE ongothread

	// On a foreign thread. We call badsignal, which will, if all
	// goes according to plan, not return.
	SUB  $4, R13
	MOVW $11, R1
	MOVW $11, R2
	MOVM.DB.W [R1,R2], (R13)
	// TODO: badsignal should not return, but it does. Issue #10139.
	//BL runtime·badsignal(SB)
	MOVW $139, R1
	MOVW R1, 4(R13)
	B    runtime·exit(SB)

ongothread:
	// Trigger a SIGSEGV panic.
	//
	// The goal is to arrange the stack so it looks like the runtime
	// function sigpanic was called from the PC that faulted. It has
	// to be sigpanic, as the stack unwinding code in traceback.go
	// looks explicitly for it.
	//
	// To do this we call into runtime·setsigsegv, which sets the
	// appropriate state inside the g object. We give it the faulting
	// PC on the stack, then put it in the LR before calling sigpanic.
	MOVM.DB.W [R1,R2], (R13)
	BL runtime·setsigsegv(SB)
	MOVM.IA.W (R13), [R1,R2]

	SUB $4, R13
	MOVW R1, 0(R13)
	MOVW R2, R14
	B runtime·sigpanic(SB)