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