// Copyright 2025 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. package asmgen var ArchARM64 = &Arch{ Name: "arm64", WordBits: 64, WordBytes: 8, CarrySafeLoop: true, regs: []string{ // R18 is the platform register. // R27 is the assembler/linker temporary (which we could potentially use but don't). // R28 is g. // R29 is FP. // R30 is LR. "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R19", "R20", "R21", "R22", "R23", "R24", "R25", "R26", }, reg0: "ZR", mov: "MOVD", add: "ADD", adds: "ADDS", adc: "ADC", adcs: "ADCS", sub: "SUB", subs: "SUBS", sbc: "SBC", sbcs: "SBCS", mul: "MUL", mulhi: "UMULH", lsh: "LSL", rsh: "LSR", and: "AND", or: "ORR", xor: "EOR", addWords: "ADD %[1]s<<3, %[2]s, %[3]s", jmpZero: "CBZ %s, %s", jmpNonZero: "CBNZ %s, %s", loadIncN: arm64LoadIncN, loadDecN: arm64LoadDecN, storeIncN: arm64StoreIncN, storeDecN: arm64StoreDecN, } func arm64LoadIncN(a *Asm, p RegPtr, regs []Reg) { if len(regs) == 1 { a.Printf("\tMOVD.P %d(%s), %s\n", a.Arch.WordBytes, p, regs[0]) return } a.Printf("\tLDP.P %d(%s), (%s, %s)\n", len(regs)*a.Arch.WordBytes, p, regs[0], regs[1]) var i int for i = 2; i+2 <= len(regs); i += 2 { a.Printf("\tLDP %d(%s), (%s, %s)\n", (i-len(regs))*a.Arch.WordBytes, p, regs[i], regs[i+1]) } if i < len(regs) { a.Printf("\tMOVD %d(%s), %s\n", -1*a.Arch.WordBytes, p, regs[i]) } } func arm64LoadDecN(a *Asm, p RegPtr, regs []Reg) { if len(regs) == 1 { a.Printf("\tMOVD.W -%d(%s), %s\n", a.Arch.WordBytes, p, regs[0]) return } a.Printf("\tLDP.W %d(%s), (%s, %s)\n", -len(regs)*a.Arch.WordBytes, p, regs[len(regs)-1], regs[len(regs)-2]) var i int for i = 2; i+2 <= len(regs); i += 2 { a.Printf("\tLDP %d(%s), (%s, %s)\n", i*a.Arch.WordBytes, p, regs[len(regs)-1-i], regs[len(regs)-2-i]) } if i < len(regs) { a.Printf("\tMOVD %d(%s), %s\n", i*a.Arch.WordBytes, p, regs[0]) } } func arm64StoreIncN(a *Asm, p RegPtr, regs []Reg) { if len(regs) == 1 { a.Printf("\tMOVD.P %s, %d(%s)\n", regs[0], a.Arch.WordBytes, p) return } a.Printf("\tSTP.P (%s, %s), %d(%s)\n", regs[0], regs[1], len(regs)*a.Arch.WordBytes, p) var i int for i = 2; i+2 <= len(regs); i += 2 { a.Printf("\tSTP (%s, %s), %d(%s)\n", regs[i], regs[i+1], (i-len(regs))*a.Arch.WordBytes, p) } if i < len(regs) { a.Printf("\tMOVD %s, %d(%s)\n", regs[i], -1*a.Arch.WordBytes, p) } } func arm64StoreDecN(a *Asm, p RegPtr, regs []Reg) { if len(regs) == 1 { a.Printf("\tMOVD.W %s, -%d(%s)\n", regs[0], a.Arch.WordBytes, p) return } a.Printf("\tSTP.W (%s, %s), %d(%s)\n", regs[len(regs)-1], regs[len(regs)-2], -len(regs)*a.Arch.WordBytes, p) var i int for i = 2; i+2 <= len(regs); i += 2 { a.Printf("\tSTP (%s, %s), %d(%s)\n", regs[len(regs)-1-i], regs[len(regs)-2-i], i*a.Arch.WordBytes, p) } if i < len(regs) { a.Printf("\tMOVD %s, %d(%s)\n", regs[0], i*a.Arch.WordBytes, p) } }