github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/compiler/arch_arm64.go (about)

     1  package compiler
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/wasilibs/wazerox/internal/asm"
     7  	"github.com/wasilibs/wazerox/internal/asm/arm64"
     8  )
     9  
    10  // init initializes variables for the arm64 architecture
    11  func init() {
    12  	newArchContext = newArchContextImpl
    13  	registerNameFn = arm64.RegisterName
    14  	unreservedGeneralPurposeRegisters = arm64UnreservedGeneralPurposeRegisters
    15  	unreservedVectorRegisters = arm64UnreservedVectorRegisters
    16  }
    17  
    18  // archContext is embedded in callEngine in order to store architecture-specific data.
    19  type archContext struct {
    20  	// compilerCallReturnAddress holds the absolute return address for nativecall.
    21  	// The value is set whenever nativecall is executed and done in compiler_arm64.s
    22  	// Native code can return to the ce.execWasmFunction's main loop back by
    23  	// executing "ret" instruction with this value. See arm64Compiler.exit.
    24  	// Note: this is only used by Compiler code so mark this as nolint.
    25  	compilerCallReturnAddress uint64 //nolint
    26  
    27  	// Loading large constants in arm64 is a bit costly, so we place the following
    28  	// consts on callEngine struct so that we can quickly access them during various operations.
    29  
    30  	// minimum32BitSignedInt is used for overflow check for 32-bit signed division.
    31  	// Note: this can be obtained by moving $1 and doing left-shift with 31, but it is
    32  	// slower than directly loading from this location.
    33  	minimum32BitSignedInt int32
    34  	// Note: this can be obtained by moving $1 and doing left-shift with 63, but it is
    35  	// slower than directly loading from this location.
    36  	// minimum64BitSignedInt is used for overflow check for 64-bit signed division.
    37  	minimum64BitSignedInt int64
    38  }
    39  
    40  // newArchContextImpl implements newArchContext for amd64 architecture.
    41  func newArchContextImpl() archContext {
    42  	return archContext{
    43  		minimum32BitSignedInt: math.MinInt32,
    44  		minimum64BitSignedInt: math.MinInt64,
    45  	}
    46  }
    47  
    48  // newCompiler returns a new compiler interface which can be used to compile the given function instance.
    49  // Note: ir param can be nil for host functions.
    50  func newCompiler() compiler {
    51  	return newArm64Compiler()
    52  }
    53  
    54  func registerMaskShift(r asm.Register) (ret int) {
    55  	ret = int(r - arm64.RegR0)
    56  	if r > arm64.RegSP {
    57  		// Skips arm64.RegSP which is not a real register.
    58  		ret--
    59  	}
    60  	return
    61  }
    62  
    63  func registerFromMaskShift(s int) asm.Register {
    64  	if s < 32 {
    65  		return arm64.RegR0 + asm.Register(s)
    66  	} else {
    67  		// Skips arm64.RegSP which is not a real register.
    68  		return arm64.RegR0 + asm.Register(s) + 1
    69  	}
    70  }