1 // Copyright 2014 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 ignore
6 7 // Generate Windows callback assembly file.
8 // This was copied from the Go repository and modified to generate non-Windows assembly files.
9 10 package main
11 12 import (
13 "bytes"
14 "fmt"
15 "os"
16 )
17 18 const maxCallback = 2000
19 20 func genasm386() {
21 var buf bytes.Buffer
22 23 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
24 25 //go:build linux
26 27 // External code calls into callbackasm at an offset corresponding
28 // to the callback index. Callbackasm is a table of MOVL and JMP instructions.
29 // The MOVL instruction loads CX with the callback index, and the
30 // JMP instruction branches to callbackasm1.
31 // callbackasm1 takes the callback index from CX and
32 // indexes into an array that stores information about each callback.
33 // It then calls the Go implementation for that callback.
34 #include "textflag.h"
35 36 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
37 `)
38 for i := 0; i < maxCallback; i++ {
39 fmt.Fprintf(&buf, "\tMOVL $%d, CX\n", i)
40 buf.WriteString("\tJMP callbackasm1(SB)\n")
41 }
42 if err := os.WriteFile("zcallback_386.s", buf.Bytes(), 0644); err != nil {
43 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
44 os.Exit(2)
45 }
46 }
47 48 func genasmAmd64() {
49 var buf bytes.Buffer
50 51 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
52 53 //go:build darwin || freebsd || linux || netbsd
54 55 // runtime·callbackasm is called by external code to
56 // execute Go implemented callback function. It is not
57 // called from the start, instead runtime·compilecallback
58 // always returns address into runtime·callbackasm offset
59 // appropriately so different callbacks start with different
60 // CALL instruction in runtime·callbackasm. This determines
61 // which Go callback function is executed later on.
62 #include "textflag.h"
63 64 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
65 `)
66 for i := 0; i < maxCallback; i++ {
67 buf.WriteString("\tCALL callbackasm1(SB)\n")
68 }
69 if err := os.WriteFile("zcallback_amd64.s", buf.Bytes(), 0644); err != nil {
70 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
71 os.Exit(2)
72 }
73 }
74 75 func genasmArm() {
76 var buf bytes.Buffer
77 78 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
79 80 //go:build linux
81 82 // External code calls into callbackasm at an offset corresponding
83 // to the callback index. Callbackasm is a table of MOVW and B instructions.
84 // The MOVW instruction loads R12 with the callback index, and the
85 // B instruction branches to callbackasm1.
86 // callbackasm1 takes the callback index from R12 and
87 // indexes into an array that stores information about each callback.
88 // It then calls the Go implementation for that callback.
89 #include "textflag.h"
90 91 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
92 `)
93 for i := 0; i < maxCallback; i++ {
94 fmt.Fprintf(&buf, "\tMOVW $%d, R12\n", i)
95 buf.WriteString("\tB callbackasm1(SB)\n")
96 }
97 if err := os.WriteFile("zcallback_arm.s", buf.Bytes(), 0644); err != nil {
98 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
99 os.Exit(2)
100 }
101 }
102 103 func genasmArm64() {
104 var buf bytes.Buffer
105 106 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
107 108 //go:build darwin || freebsd || linux || netbsd
109 110 // External code calls into callbackasm at an offset corresponding
111 // to the callback index. Callbackasm is a table of MOV and B instructions.
112 // The MOV instruction loads R12 with the callback index, and the
113 // B instruction branches to callbackasm1.
114 // callbackasm1 takes the callback index from R12 and
115 // indexes into an array that stores information about each callback.
116 // It then calls the Go implementation for that callback.
117 #include "textflag.h"
118 119 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
120 `)
121 for i := 0; i < maxCallback; i++ {
122 fmt.Fprintf(&buf, "\tMOVD $%d, R12\n", i)
123 buf.WriteString("\tB callbackasm1(SB)\n")
124 }
125 if err := os.WriteFile("zcallback_arm64.s", buf.Bytes(), 0644); err != nil {
126 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
127 os.Exit(2)
128 }
129 }
130 131 func genasmLoong64() {
132 var buf bytes.Buffer
133 134 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
135 136 //go:build darwin || freebsd || linux || netbsd
137 138 // External code calls into callbackasm at an offset corresponding
139 // to the callback index. Callbackasm is a table of MOVV and JMP instructions.
140 // The MOVV instruction loads R12 with the callback index, and the
141 // JMP instruction branches to callbackasm1.
142 // callbackasm1 takes the callback index from R12 and
143 // indexes into an array that stores information about each callback.
144 // It then calls the Go implementation for that callback.
145 #include "textflag.h"
146 147 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
148 `)
149 for i := 0; i < maxCallback; i++ {
150 fmt.Fprintf(&buf, "\tMOVV $%d, R12\n", i)
151 buf.WriteString("\tJMP callbackasm1(SB)\n")
152 }
153 if err := os.WriteFile("zcallback_loong64.s", buf.Bytes(), 0644); err != nil {
154 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
155 os.Exit(2)
156 }
157 }
158 159 func genasmPpc64le() {
160 var buf bytes.Buffer
161 162 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
163 164 //go:build linux
165 166 // External code calls into callbackasm at an offset corresponding
167 // to the callback index. Callbackasm is a table of MOVD and BR instructions.
168 // The MOVD instruction loads R11 with the callback index, and the
169 // BR instruction branches to callbackasm1.
170 // callbackasm1 takes the callback index from R11 and
171 // indexes into an array that stores information about each callback.
172 // It then calls the Go implementation for that callback.
173 #include "textflag.h"
174 175 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
176 `)
177 for i := 0; i < maxCallback; i++ {
178 fmt.Fprintf(&buf, "\tMOVD $%d, R11\n", i)
179 buf.WriteString("\tBR callbackasm1(SB)\n")
180 }
181 if err := os.WriteFile("zcallback_ppc64le.s", buf.Bytes(), 0644); err != nil {
182 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
183 os.Exit(2)
184 }
185 }
186 187 func genasmRiscv64() {
188 var buf bytes.Buffer
189 190 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
191 192 //go:build darwin || freebsd || linux || netbsd
193 194 // External code calls into callbackasm at an offset corresponding
195 // to the callback index. Callbackasm is a table of MOV and JMP instructions.
196 // Since Go 1.26, MOV instructions with immediate values lower than or equal to 32
197 // are encoded in 2 bytes rather than 4 bytes, which breaks the assumption that each
198 // callback entry is 8 bytes long. Therefore, for callback indices less than or equal to 32,
199 // add a PCALIGN directive to align the next instruction to an 8-byte boundary.
200 // The MOV instruction loads X7 with the callback index, and the
201 // JMP instruction branches to callbackasm1.
202 // callbackasm1 takes the callback index from X7 and
203 // indexes into an array that stores information about each callback.
204 // It then calls the Go implementation for that callback.
205 #include "textflag.h"
206 207 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
208 `)
209 for i := 0; i < maxCallback; i++ {
210 space := " "
211 if i <= 32 {
212 fmt.Fprintf(&buf, "\tPCALIGN $8\n")
213 space = " "
214 }
215 fmt.Fprintf(&buf, "\tMOV%s$%d, X7\n", space, i)
216 fmt.Fprintf(&buf, "\tJMP%scallbackasm1(SB)\n", space)
217 }
218 if err := os.WriteFile("zcallback_riscv64.s", buf.Bytes(), 0644); err != nil {
219 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
220 os.Exit(2)
221 }
222 }
223 224 func genasmS390x() {
225 var buf bytes.Buffer
226 227 buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
228 229 //go:build linux
230 231 // External code calls into callbackasm at an offset corresponding
232 // to the callback index. Callbackasm is a table of MOVD and BR instructions.
233 // The MOVD instruction loads R0 with the callback index, and the
234 // BR instruction branches to callbackasm1.
235 // callbackasm1 takes the callback index from R0 and
236 // indexes into an array that stores information about each callback.
237 // It then calls the Go implementation for that callback.
238 // NOTE: We use R0 instead of R11 because R11 is callee-saved on S390X.
239 #include "textflag.h"
240 241 TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
242 `)
243 for i := 0; i < maxCallback; i++ {
244 fmt.Fprintf(&buf, "\tMOVD $%d, R0\n", i)
245 buf.WriteString("\tBR callbackasm1(SB)\n")
246 }
247 if err := os.WriteFile("zcallback_s390x.s", buf.Bytes(), 0644); err != nil {
248 fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
249 os.Exit(2)
250 }
251 }
252 253 func main() {
254 genasm386()
255 genasmAmd64()
256 genasmArm()
257 genasmArm64()
258 genasmLoong64()
259 genasmPpc64le()
260 genasmRiscv64()
261 genasmS390x()
262 }
263