1
2
3
4
5 package main
6
7 import "strings"
8
9 var regNamesWasm = []string{
10 "R0",
11 "R1",
12 "R2",
13 "R3",
14 "R4",
15 "R5",
16 "R6",
17 "R7",
18 "R8",
19 "R9",
20 "R10",
21 "R11",
22 "R12",
23 "R13",
24 "R14",
25 "R15",
26
27 "F0",
28 "F1",
29 "F2",
30 "F3",
31 "F4",
32 "F5",
33 "F6",
34 "F7",
35 "F8",
36 "F9",
37 "F10",
38 "F11",
39 "F12",
40 "F13",
41 "F14",
42 "F15",
43
44 "F16",
45 "F17",
46 "F18",
47 "F19",
48 "F20",
49 "F21",
50 "F22",
51 "F23",
52 "F24",
53 "F25",
54 "F26",
55 "F27",
56 "F28",
57 "F29",
58 "F30",
59 "F31",
60
61 "V0",
62 "V1",
63 "V2",
64 "V3",
65 "V4",
66 "V5",
67 "V6",
68 "V7",
69 "V8",
70 "V9",
71 "V10",
72 "V11",
73 "V12",
74 "V13",
75 "V14",
76 "V15",
77
78 "SP",
79 "g",
80
81
82 "SB",
83 }
84
85 func init() {
86
87 num := map[string]int{}
88 for i, name := range regNamesWasm {
89 num[name] = i
90 }
91 buildReg := func(s string) regMask {
92 m := regMask{}
93 for _, r := range strings.Split(s, " ") {
94 if n, ok := num[r]; ok {
95 m = m.addReg(uint(n))
96 continue
97 }
98 panic("register " + r + " not found")
99 }
100 return m
101 }
102
103 var (
104 gp = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15")
105 fp32 = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
106 fp64 = buildReg("F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
107 v128 = buildReg("V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15")
108 gpsp = gp.union(buildReg("SP"))
109 gpspsb = gpsp.union(buildReg("SB"))
110
111
112 callerSave = gp.union(fp32).union(fp64).union(v128).union(buildReg("g"))
113 )
114
115
116 var (
117 gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
118 gp11 = regInfo{inputs: []regMask{gpsp}, outputs: []regMask{gp}}
119 gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: []regMask{gp}}
120 gp31 = regInfo{inputs: []regMask{gpsp, gpsp, gpsp}, outputs: []regMask{gp}}
121 fp32_01 = regInfo{inputs: nil, outputs: []regMask{fp32}}
122 fp32_11 = regInfo{inputs: []regMask{fp32}, outputs: []regMask{fp32}}
123 fp32_21 = regInfo{inputs: []regMask{fp32, fp32}, outputs: []regMask{fp32}}
124 fp32_21gp = regInfo{inputs: []regMask{fp32, fp32}, outputs: []regMask{gp}}
125 fp64_01 = regInfo{inputs: nil, outputs: []regMask{fp64}}
126 fp64_11 = regInfo{inputs: []regMask{fp64}, outputs: []regMask{fp64}}
127 fp64_21 = regInfo{inputs: []regMask{fp64, fp64}, outputs: []regMask{fp64}}
128 fp64_21gp = regInfo{inputs: []regMask{fp64, fp64}, outputs: []regMask{gp}}
129
130 gpload = regInfo{inputs: []regMask{gpspsb, regMask{}}, outputs: []regMask{gp}}
131 gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, regMask{}}}
132 fp32load = regInfo{inputs: []regMask{gpspsb, regMask{}}, outputs: []regMask{fp32}}
133 fp32store = regInfo{inputs: []regMask{gpspsb, fp32, regMask{}}}
134 fp64load = regInfo{inputs: []regMask{gpspsb, regMask{}}, outputs: []regMask{fp64}}
135 fp64store = regInfo{inputs: []regMask{gpspsb, fp64, regMask{}}}
136
137 v01 = regInfo{inputs: nil, outputs: []regMask{v128}}
138 vload = regInfo{inputs: []regMask{gpspsb, regMask{}}, outputs: []regMask{v128}}
139 vstore = regInfo{inputs: []regMask{gpspsb, v128, regMask{}}}
140
141 v11 = regInfo{inputs: []regMask{v128}, outputs: []regMask{v128}}
142 v21 = regInfo{inputs: []regMask{v128, v128}, outputs: []regMask{v128}}
143 v31 = regInfo{inputs: []regMask{v128, v128, v128}, outputs: []regMask{v128}}
144
145 v11gp = regInfo{inputs: []regMask{v128}, outputs: []regMask{gp}}
146 v11fp32 = regInfo{inputs: []regMask{v128}, outputs: []regMask{fp32}}
147 v11fp64 = regInfo{inputs: []regMask{v128}, outputs: []regMask{fp64}}
148
149 v2gpv = regInfo{inputs: []regMask{v128, v128, gp}, outputs: []regMask{v128}}
150
151 v1gpv = regInfo{inputs: []regMask{v128, gp}, outputs: []regMask{v128}}
152 v1fp32v = regInfo{inputs: []regMask{v128, fp32}, outputs: []regMask{v128}}
153 v1fp64v = regInfo{inputs: []regMask{v128, fp64}, outputs: []regMask{v128}}
154
155 gpv = regInfo{inputs: []regMask{gp}, outputs: []regMask{v128}}
156 fp32v = regInfo{inputs: []regMask{fp32}, outputs: []regMask{v128}}
157 fp64v = regInfo{inputs: []regMask{fp64}, outputs: []regMask{v128}}
158 )
159
160 var WasmOps = []opData{
161 {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true},
162 {name: "LoweredTailCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true, tailCall: true},
163 {name: "LoweredTailCallInter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true, tailCall: true},
164 {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, regMask{}}, clobbers: callerSave}, aux: "CallOff", call: true},
165 {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true},
166
167 {name: "LoweredAddr", argLength: 1, reg: gp11, aux: "SymOff", rematerializeable: true, symEffect: "Addr", earlyOk: true},
168 {name: "LoweredMove", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Int64", addrSinkArg0: true, addrSinkArg1: true},
169 {name: "LoweredZero", argLength: 2, reg: regInfo{inputs: []regMask{gp}}, aux: "Int64", addrSinkArg0: true},
170
171 {name: "LoweredGetClosurePtr", reg: gp01},
172 {name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
173 {name: "LoweredGetCallerSP", argLength: 1, reg: gp01, rematerializeable: true},
174 {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp}}, nilCheck: true, faultOnNilArg0: true},
175 {name: "LoweredWB", argLength: 1, reg: regInfo{clobbers: callerSave, outputs: []regMask{gp}}, aux: "Int64"},
176
177
178
179
180
181
182
183
184 {name: "LoweredConvert", argLength: 2, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}},
185
186
187
188 {name: "Select", asm: "Select", argLength: 3, reg: gp31, earlyOk: true},
189 {name: "SelectV", asm: "Select", argLength: 3, reg: v2gpv, earlyOk: true},
190
191 {name: "I64Load8U", asm: "I64Load8U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt8", addrSinkArg0: true},
192 {name: "I64Load8S", asm: "I64Load8S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int8", addrSinkArg0: true},
193 {name: "I64Load16U", asm: "I64Load16U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt16", addrSinkArg0: true},
194 {name: "I64Load16S", asm: "I64Load16S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int16", addrSinkArg0: true},
195 {name: "I64Load32U", asm: "I64Load32U", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt32", addrSinkArg0: true},
196 {name: "I64Load32S", asm: "I64Load32S", argLength: 2, reg: gpload, aux: "Int64", typ: "Int32", addrSinkArg0: true},
197 {name: "I64Load", asm: "I64Load", argLength: 2, reg: gpload, aux: "Int64", typ: "UInt64", addrSinkArg0: true},
198 {name: "I64Store8", asm: "I64Store8", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem", addrSinkArg0: true},
199 {name: "I64Store16", asm: "I64Store16", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem", addrSinkArg0: true},
200 {name: "I64Store32", asm: "I64Store32", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem", addrSinkArg0: true},
201 {name: "I64Store", asm: "I64Store", argLength: 3, reg: gpstore, aux: "Int64", typ: "Mem", addrSinkArg0: true},
202
203 {name: "F32Load", asm: "F32Load", argLength: 2, reg: fp32load, aux: "Int64", typ: "Float32", addrSinkArg0: true},
204 {name: "F64Load", asm: "F64Load", argLength: 2, reg: fp64load, aux: "Int64", typ: "Float64", addrSinkArg0: true},
205 {name: "F32Store", asm: "F32Store", argLength: 3, reg: fp32store, aux: "Int64", typ: "Mem", addrSinkArg0: true},
206 {name: "F64Store", asm: "F64Store", argLength: 3, reg: fp64store, aux: "Int64", typ: "Mem", addrSinkArg0: true},
207
208 {name: "I64Const", reg: gp01, aux: "Int64", rematerializeable: true, typ: "Int64", earlyOk: true},
209 {name: "F32Const", reg: fp32_01, aux: "Float32", rematerializeable: true, typ: "Float32", earlyOk: true},
210 {name: "F64Const", reg: fp64_01, aux: "Float64", rematerializeable: true, typ: "Float64", earlyOk: true},
211
212 {name: "V128Load", asm: "V128Load", argLength: 2, reg: vload, aux: "Int64", typ: "V128", addrSinkArg0: true},
213 {name: "V128Store", asm: "V128Store", argLength: 3, reg: vstore, aux: "Int64", typ: "Mem", addrSinkArg0: true},
214 {name: "V128Zero", argLength: 0, reg: v01, asm: "V128Const", typ: "V128"},
215
216 {name: "I64Eqz", asm: "I64Eqz", argLength: 1, reg: gp11, typ: "Bool", earlyOk: true},
217 {name: "I64Eq", asm: "I64Eq", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
218 {name: "I64Ne", asm: "I64Ne", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
219 {name: "I64LtS", asm: "I64LtS", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
220 {name: "I64LtU", asm: "I64LtU", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
221 {name: "I64GtS", asm: "I64GtS", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
222 {name: "I64GtU", asm: "I64GtU", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
223 {name: "I64LeS", asm: "I64LeS", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
224 {name: "I64LeU", asm: "I64LeU", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
225 {name: "I64GeS", asm: "I64GeS", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
226 {name: "I64GeU", asm: "I64GeU", argLength: 2, reg: gp21, typ: "Bool", earlyOk: true},
227
228 {name: "F32Eq", asm: "F32Eq", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
229 {name: "F32Ne", asm: "F32Ne", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
230 {name: "F32Lt", asm: "F32Lt", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
231 {name: "F32Gt", asm: "F32Gt", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
232 {name: "F32Le", asm: "F32Le", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
233 {name: "F32Ge", asm: "F32Ge", argLength: 2, reg: fp32_21gp, typ: "Bool", earlyOk: true},
234
235 {name: "F64Eq", asm: "F64Eq", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
236 {name: "F64Ne", asm: "F64Ne", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
237 {name: "F64Lt", asm: "F64Lt", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
238 {name: "F64Gt", asm: "F64Gt", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
239 {name: "F64Le", asm: "F64Le", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
240 {name: "F64Ge", asm: "F64Ge", argLength: 2, reg: fp64_21gp, typ: "Bool", earlyOk: true},
241
242 {name: "I64Add", asm: "I64Add", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
243 {name: "I64AddConst", asm: "I64Add", argLength: 1, reg: gp11, aux: "Int64", typ: "Int64", earlyOk: true},
244 {name: "I64Sub", asm: "I64Sub", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
245 {name: "I64Mul", asm: "I64Mul", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
246 {name: "I64DivS", asm: "I64DivS", argLength: 2, reg: gp21, typ: "Int64"},
247 {name: "I64DivU", asm: "I64DivU", argLength: 2, reg: gp21, typ: "Int64"},
248 {name: "I64RemS", asm: "I64RemS", argLength: 2, reg: gp21, typ: "Int64"},
249 {name: "I64RemU", asm: "I64RemU", argLength: 2, reg: gp21, typ: "Int64"},
250 {name: "I64And", asm: "I64And", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
251 {name: "I64Or", asm: "I64Or", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
252 {name: "I64Xor", asm: "I64Xor", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
253 {name: "I64Shl", asm: "I64Shl", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
254 {name: "I64ShrS", asm: "I64ShrS", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
255 {name: "I64ShrU", asm: "I64ShrU", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
256
257 {name: "F32Neg", asm: "F32Neg", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
258 {name: "F32Add", asm: "F32Add", argLength: 2, reg: fp32_21, typ: "Float32", earlyOk: true},
259 {name: "F32Sub", asm: "F32Sub", argLength: 2, reg: fp32_21, typ: "Float32", earlyOk: true},
260 {name: "F32Mul", asm: "F32Mul", argLength: 2, reg: fp32_21, typ: "Float32", earlyOk: true},
261 {name: "F32Div", asm: "F32Div", argLength: 2, reg: fp32_21, typ: "Float32", earlyOk: true},
262
263 {name: "F64Neg", asm: "F64Neg", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
264 {name: "F64Add", asm: "F64Add", argLength: 2, reg: fp64_21, typ: "Float64", earlyOk: true},
265 {name: "F64Sub", asm: "F64Sub", argLength: 2, reg: fp64_21, typ: "Float64", earlyOk: true},
266 {name: "F64Mul", asm: "F64Mul", argLength: 2, reg: fp64_21, typ: "Float64", earlyOk: true},
267 {name: "F64Div", asm: "F64Div", argLength: 2, reg: fp64_21, typ: "Float64", earlyOk: true},
268
269 {name: "I64TruncSatF64S", asm: "I64TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64", earlyOk: true},
270 {name: "I64TruncSatF64U", asm: "I64TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64", earlyOk: true},
271 {name: "I64TruncSatF32S", asm: "I64TruncSatF32S", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64", earlyOk: true},
272 {name: "I64TruncSatF32U", asm: "I64TruncSatF32U", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64", earlyOk: true},
273 {name: "F32ConvertI64S", asm: "F32ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32", earlyOk: true},
274 {name: "F32ConvertI64U", asm: "F32ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32", earlyOk: true},
275 {name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64", earlyOk: true},
276 {name: "F64ConvertI64U", asm: "F64ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64", earlyOk: true},
277 {name: "F32DemoteF64", asm: "F32DemoteF64", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{fp32}}, typ: "Float32", earlyOk: true},
278 {name: "F64PromoteF32", asm: "F64PromoteF32", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{fp64}}, typ: "Float64", earlyOk: true},
279
280 {name: "I64Extend8S", asm: "I64Extend8S", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
281 {name: "I64Extend16S", asm: "I64Extend16S", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
282 {name: "I64Extend32S", asm: "I64Extend32S", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
283
284 {name: "F32Sqrt", asm: "F32Sqrt", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
285 {name: "F32Trunc", asm: "F32Trunc", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
286 {name: "F32Ceil", asm: "F32Ceil", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
287 {name: "F32Floor", asm: "F32Floor", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
288 {name: "F32Nearest", asm: "F32Nearest", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
289 {name: "F32Abs", asm: "F32Abs", argLength: 1, reg: fp32_11, typ: "Float32", earlyOk: true},
290 {name: "F32Copysign", asm: "F32Copysign", argLength: 2, reg: fp32_21, typ: "Float32", earlyOk: true},
291
292 {name: "F64Sqrt", asm: "F64Sqrt", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
293 {name: "F64Trunc", asm: "F64Trunc", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
294 {name: "F64Ceil", asm: "F64Ceil", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
295 {name: "F64Floor", asm: "F64Floor", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
296 {name: "F64Nearest", asm: "F64Nearest", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
297 {name: "F64Abs", asm: "F64Abs", argLength: 1, reg: fp64_11, typ: "Float64", earlyOk: true},
298 {name: "F64Copysign", asm: "F64Copysign", argLength: 2, reg: fp64_21, typ: "Float64", earlyOk: true},
299
300 {name: "I64Ctz", asm: "I64Ctz", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
301 {name: "I64Clz", asm: "I64Clz", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
302 {name: "I32Rotl", asm: "I32Rotl", argLength: 2, reg: gp21, typ: "Int32", earlyOk: true},
303 {name: "I64Rotl", asm: "I64Rotl", argLength: 2, reg: gp21, typ: "Int64", earlyOk: true},
304 {name: "I64Popcnt", asm: "I64Popcnt", argLength: 1, reg: gp11, typ: "Int64", earlyOk: true},
305 }
306
307 WasmOps = append(WasmOps, simdWasmOps(vload, vstore, v11, v21, v31, v11gp, v11fp32, v11fp64, v1gpv, v1fp32v, v1fp64v, gpv, fp32v, fp64v)...)
308
309 archs = append(archs, arch{
310 name: "Wasm",
311 pkg: "cmd/internal/obj/wasm",
312 genfile: "../../wasm/ssa.go",
313 genSIMDfile: "../../wasm/simdssa.go",
314 ops: WasmOps,
315 blocks: nil,
316 regnames: regNamesWasm,
317 gpregmask: gp,
318 fpregmask: fp32.union(fp64),
319 simdregmask: v128,
320 fp32regmask: fp32,
321 fp64regmask: fp64,
322 framepointerreg: -1,
323 linkreg: -1,
324 })
325 }
326
View as plain text