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