arm64.mx raw
1 // Copyright 2025 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 package asmgen
6
7 var ArchARM64 = &Arch{
8 Name: "arm64",
9 WordBits: 64,
10 WordBytes: 8,
11 CarrySafeLoop: true,
12
13 regs: [][]byte{
14 // R18 is the platform register.
15 // R27 is the assembler/linker temporary (which we could potentially use but don't).
16 // R28 is g.
17 // R29 is FP.
18 // R30 is LR.
19 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9",
20 "R10", "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R19",
21 "R20", "R21", "R22", "R23", "R24", "R25", "R26",
22 },
23 reg0: "ZR",
24
25 mov: "MOVD",
26 add: "ADD",
27 adds: "ADDS",
28 adc: "ADC",
29 adcs: "ADCS",
30 sub: "SUB",
31 subs: "SUBS",
32 sbc: "SBC",
33 sbcs: "SBCS",
34 mul: "MUL",
35 mulhi: "UMULH",
36 lsh: "LSL",
37 rsh: "LSR",
38 and: "AND",
39 or: "ORR",
40 xor: "EOR",
41
42 addWords: "ADD %[1]s<<3, %[2]s, %[3]s",
43
44 jmpZero: "CBZ %s, %s",
45 jmpNonZero: "CBNZ %s, %s",
46
47 loadIncN: arm64LoadIncN,
48 loadDecN: arm64LoadDecN,
49 storeIncN: arm64StoreIncN,
50 storeDecN: arm64StoreDecN,
51 }
52
53 func arm64LoadIncN(a *Asm, p RegPtr, regs []Reg) {
54 if len(regs) == 1 {
55 a.Printf("\tMOVD.P %d(%s), %s\n", a.Arch.WordBytes, p, regs[0])
56 return
57 }
58 a.Printf("\tLDP.P %d(%s), (%s, %s)\n", len(regs)*a.Arch.WordBytes, p, regs[0], regs[1])
59 var i int
60 for i = 2; i+2 <= len(regs); i += 2 {
61 a.Printf("\tLDP %d(%s), (%s, %s)\n", (i-len(regs))*a.Arch.WordBytes, p, regs[i], regs[i+1])
62 }
63 if i < len(regs) {
64 a.Printf("\tMOVD %d(%s), %s\n", -1*a.Arch.WordBytes, p, regs[i])
65 }
66 }
67
68 func arm64LoadDecN(a *Asm, p RegPtr, regs []Reg) {
69 if len(regs) == 1 {
70 a.Printf("\tMOVD.W -%d(%s), %s\n", a.Arch.WordBytes, p, regs[0])
71 return
72 }
73 a.Printf("\tLDP.W %d(%s), (%s, %s)\n", -len(regs)*a.Arch.WordBytes, p, regs[len(regs)-1], regs[len(regs)-2])
74 var i int
75 for i = 2; i+2 <= len(regs); i += 2 {
76 a.Printf("\tLDP %d(%s), (%s, %s)\n", i*a.Arch.WordBytes, p, regs[len(regs)-1-i], regs[len(regs)-2-i])
77 }
78 if i < len(regs) {
79 a.Printf("\tMOVD %d(%s), %s\n", i*a.Arch.WordBytes, p, regs[0])
80 }
81 }
82
83 func arm64StoreIncN(a *Asm, p RegPtr, regs []Reg) {
84 if len(regs) == 1 {
85 a.Printf("\tMOVD.P %s, %d(%s)\n", regs[0], a.Arch.WordBytes, p)
86 return
87 }
88 a.Printf("\tSTP.P (%s, %s), %d(%s)\n", regs[0], regs[1], len(regs)*a.Arch.WordBytes, p)
89 var i int
90 for i = 2; i+2 <= len(regs); i += 2 {
91 a.Printf("\tSTP (%s, %s), %d(%s)\n", regs[i], regs[i+1], (i-len(regs))*a.Arch.WordBytes, p)
92 }
93 if i < len(regs) {
94 a.Printf("\tMOVD %s, %d(%s)\n", regs[i], -1*a.Arch.WordBytes, p)
95 }
96 }
97
98 func arm64StoreDecN(a *Asm, p RegPtr, regs []Reg) {
99 if len(regs) == 1 {
100 a.Printf("\tMOVD.W %s, -%d(%s)\n", regs[0], a.Arch.WordBytes, p)
101 return
102 }
103 a.Printf("\tSTP.W (%s, %s), %d(%s)\n", regs[len(regs)-1], regs[len(regs)-2], -len(regs)*a.Arch.WordBytes, p)
104 var i int
105 for i = 2; i+2 <= len(regs); i += 2 {
106 a.Printf("\tSTP (%s, %s), %d(%s)\n", regs[len(regs)-1-i], regs[len(regs)-2-i], i*a.Arch.WordBytes, p)
107 }
108 if i < len(regs) {
109 a.Printf("\tMOVD %s, %d(%s)\n", regs[0], i*a.Arch.WordBytes, p)
110 }
111 }
112