1
2
3
4
5 package riscv64asm
6
7 import (
8 "strings"
9 )
10
11
12
13
14 func GNUSyntax(inst Inst) string {
15 hasVectorArg := false
16 var args []string
17 for _, a := range inst.Args {
18 if a == nil {
19 break
20 }
21 args = append(args, strings.ToLower(a.String()))
22 if r, ok := a.(Reg); ok {
23 hasVectorArg = hasVectorArg || (r >= V0 && r <= V31)
24 }
25 }
26
27 if hasVectorArg {
28 return gnuVectorOp(inst, args)
29 }
30
31 op := strings.ToLower(inst.Op.String())
32 gnuSyntaxSwitch:
33 switch inst.Op {
34 case ADDI, ADDIW, ANDI, SLLI, SLLIW, SRAI, SRAIW, SRLI, SRLIW, XORI:
35 if inst.Op == ADDI {
36 if inst.Args[1].(Reg) == X0 && inst.Args[0].(Reg) != X0 {
37 op = "li"
38 args[1] = args[2]
39 args = args[:len(args)-1]
40 break
41 }
42
43 if inst.Args[2].(Simm).Imm == 0 {
44 if inst.Args[0].(Reg) == X0 && inst.Args[1].(Reg) == X0 {
45 op = "nop"
46 args = nil
47 } else {
48 op = "mv"
49 args = args[:len(args)-1]
50 }
51 }
52 }
53
54 if inst.Op == ANDI && inst.Args[2].(Simm).Imm == 255 {
55 op = "zext.b"
56 args = args[:len(args)-1]
57 }
58
59 if inst.Op == ADDIW && inst.Args[2].(Simm).Imm == 0 {
60 op = "sext.w"
61 args = args[:len(args)-1]
62 }
63
64 if inst.Op == XORI && inst.Args[2].(Simm).String() == "-1" {
65 op = "not"
66 args = args[:len(args)-1]
67 }
68
69 case ORI:
70 if inst.Args[0].(Reg) == X0 {
71 simm := inst.Args[2].(Simm)
72 switch simm.Imm & 0b11111 {
73 case 0:
74 op = "prefetch.i"
75 case 1:
76 op = "prefetch.r"
77 case 3:
78 op = "prefetch.w"
79 default:
80 break gnuSyntaxSwitch
81 }
82
83 simm.Imm = simm.Imm &^ 0b11111
84 args[0] = RegOffset{inst.Args[1].(Reg), simm}.String()
85 args = args[:len(args)-2]
86 }
87
88 case ADD:
89 if inst.Args[1].(Reg) == X0 {
90 op = "mv"
91 args[1] = args[2]
92 args = args[:len(args)-1]
93 }
94
95 case BEQ:
96 if inst.Args[1].(Reg) == X0 {
97 op = "beqz"
98 args[1] = args[2]
99 args = args[:len(args)-1]
100 }
101
102 case BGE:
103 if inst.Args[1].(Reg) == X0 {
104 op = "bgez"
105 args[1] = args[2]
106 args = args[:len(args)-1]
107 } else if inst.Args[0].(Reg) == X0 {
108 op = "blez"
109 args[0], args[1] = args[1], args[2]
110 args = args[:len(args)-1]
111 }
112
113 case BLT:
114 if inst.Args[1].(Reg) == X0 {
115 op = "bltz"
116 args[1] = args[2]
117 args = args[:len(args)-1]
118 } else if inst.Args[0].(Reg) == X0 {
119 op = "bgtz"
120 args[0], args[1] = args[1], args[2]
121 args = args[:len(args)-1]
122 }
123
124 case BNE:
125 if inst.Args[1].(Reg) == X0 {
126 op = "bnez"
127 args[1] = args[2]
128 args = args[:len(args)-1]
129 }
130
131 case CSRRC:
132 if inst.Args[0].(Reg) == X0 {
133 op = "csrc"
134 args[0], args[1] = args[1], args[2]
135 args = args[:len(args)-1]
136 }
137
138 case CSRRCI:
139 if inst.Args[0].(Reg) == X0 {
140 op = "csrci"
141 args[0], args[1] = args[1], args[2]
142 args = args[:len(args)-1]
143 }
144
145 case CSRRS:
146 if inst.Args[2].(Reg) == X0 {
147 switch inst.Args[1].(CSR) {
148 case FCSR:
149 op = "frcsr"
150 args = args[:len(args)-2]
151
152 case FFLAGS:
153 op = "frflags"
154 args = args[:len(args)-2]
155
156 case FRM:
157 op = "frrm"
158 args = args[:len(args)-2]
159
160
161
162 case CYCLE:
163 op = "rdcycle"
164 args = args[:len(args)-2]
165
166 case INSTRET:
167 op = "rdinstret"
168 args = args[:len(args)-2]
169
170 case TIME:
171 op = "rdtime"
172 args = args[:len(args)-2]
173
174 default:
175 op = "csrr"
176 args = args[:len(args)-1]
177 }
178 } else if inst.Args[0].(Reg) == X0 {
179 op = "csrs"
180 args[0], args[1] = args[1], args[2]
181 args = args[:len(args)-1]
182 }
183
184 case CSRRSI:
185 if inst.Args[0].(Reg) == X0 {
186 op = "csrsi"
187 args[0], args[1] = args[1], args[2]
188 args = args[:len(args)-1]
189 }
190
191 case CSRRW:
192 switch inst.Args[1].(CSR) {
193 case FCSR:
194 op = "fscsr"
195 if inst.Args[0].(Reg) == X0 {
196 args[0] = args[2]
197 args = args[:len(args)-2]
198 } else {
199 args[1] = args[2]
200 args = args[:len(args)-1]
201 }
202
203 case FFLAGS:
204 op = "fsflags"
205 if inst.Args[0].(Reg) == X0 {
206 args[0] = args[2]
207 args = args[:len(args)-2]
208 } else {
209 args[1] = args[2]
210 args = args[:len(args)-1]
211 }
212
213 case FRM:
214 op = "fsrm"
215 if inst.Args[0].(Reg) == X0 {
216 args[0] = args[2]
217 args = args[:len(args)-2]
218 } else {
219 args[1] = args[2]
220 args = args[:len(args)-1]
221 }
222
223 case CYCLE:
224 if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
225 op = "unimp"
226 args = nil
227 }
228
229 default:
230 if inst.Args[0].(Reg) == X0 {
231 op = "csrw"
232 args[0], args[1] = args[1], args[2]
233 args = args[:len(args)-1]
234 }
235 }
236
237 case CSRRWI:
238 if inst.Args[0].(Reg) == X0 {
239 op = "csrwi"
240 args[0], args[1] = args[1], args[2]
241 args = args[:len(args)-1]
242 }
243
244 case FENCE:
245 fm := inst.Enc >> 28
246 pred := inst.Args[0].(MemOrder).String()
247 succ := inst.Args[1].(MemOrder).String()
248 if fm == 0b1000 {
249 if pred == "rw" && succ == "rw" {
250 return "fence.tso"
251 }
252 return op
253 }
254
255 if pred == "w" && succ == "" {
256 return "pause"
257 }
258 if fm != 0 || pred == "" || succ == "" || (pred == "iorw" && succ == "iorw") {
259
260
261
262 return op
263 }
264
265 case FSGNJX_D:
266 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
267 op = "fabs.d"
268 args = args[:len(args)-1]
269 }
270
271 case FSGNJX_S:
272 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
273 op = "fabs.s"
274 args = args[:len(args)-1]
275 }
276
277 case FSGNJ_D:
278 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
279 op = "fmv.d"
280 args = args[:len(args)-1]
281 }
282
283 case FSGNJ_S:
284 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
285 op = "fmv.s"
286 args = args[:len(args)-1]
287 }
288
289 case FSGNJN_D:
290 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
291 op = "fneg.d"
292 args = args[:len(args)-1]
293 }
294
295 case FSGNJN_S:
296 if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
297 op = "fneg.s"
298 args = args[:len(args)-1]
299 }
300
301 case JAL:
302 if inst.Args[0].(Reg) == X0 {
303 op = "j"
304 args[0] = args[1]
305 args = args[:len(args)-1]
306 } else if inst.Args[0].(Reg) == X1 {
307 op = "jal"
308 args[0] = args[1]
309 args = args[:len(args)-1]
310 }
311
312 case JALR:
313 if inst.Args[0].(Reg) == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
314 args[0] = inst.Args[1].(RegOffset).OfsReg.String()
315 args = args[:len(args)-1]
316 }
317
318 if inst.Args[0].(Reg) == X0 {
319 if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
320 op = "ret"
321 args = nil
322 } else if inst.Args[1].(RegOffset).Ofs.Imm == 0 {
323 op = "jr"
324 args[0] = inst.Args[1].(RegOffset).OfsReg.String()
325 args = args[:len(args)-1]
326 } else {
327 op = "jr"
328 args[0] = inst.Args[1].(RegOffset).String()
329 args = args[:len(args)-1]
330 }
331 }
332
333 case SLTIU:
334 if inst.Args[2].(Simm).String() == "1" {
335 op = "seqz"
336 args = args[:len(args)-1]
337 }
338
339 case SLT:
340 if inst.Args[1].(Reg) == X0 {
341 op = "sgtz"
342 args[1] = args[2]
343 args = args[:len(args)-1]
344 } else if inst.Args[2].(Reg) == X0 {
345 op = "sltz"
346 args = args[:len(args)-1]
347 }
348
349 case SLTU:
350 if inst.Args[1].(Reg) == X0 {
351 op = "snez"
352 args[1] = args[2]
353 args = args[:len(args)-1]
354 }
355
356 case SUB:
357 if inst.Args[1].(Reg) == X0 {
358 op = "neg"
359 args[1] = args[2]
360 args = args[:len(args)-1]
361 }
362
363 case SUBW:
364 if inst.Args[1].(Reg) == X0 {
365 op = "negw"
366 args[1] = args[2]
367 args = args[:len(args)-1]
368 }
369
370 case VSETVLI, VSETIVLI:
371 args[0], args[2] = args[2], strings.ReplaceAll(args[0], " ", "")
372
373 case VSETVL:
374 args[0], args[2] = args[2], args[0]
375 }
376
377 if args != nil {
378 op += " " + strings.Join(args, ",")
379 }
380 return op
381 }
382
383 func gnuVectorOp(inst Inst, args []string) string {
384
385
386
387
388 rawArgs := inst.Args[:]
389
390 var mask string
391 var op string
392 if inst.Enc&(1<<25) == 0 {
393 if implicitMask(inst.Op) {
394 mask = "v0"
395 } else {
396 mask = "v0.t"
397 args = args[1:]
398 rawArgs = rawArgs[1:]
399 }
400 }
401
402 if len(args) > 1 {
403 if inst.Enc&0x7f == 0x7 || inst.Enc&0x7f == 0x27 {
404
405 if len(args) >= 2 {
406 args[0], args[len(args)-1] = args[len(args)-1], args[0]
407 }
408 op = pseudoRVVLoad(inst.Op)
409 } else {
410
411
412 op, args = pseudoRVVArith(inst.Op, rawArgs, args)
413
414 if len(args) == 3 {
415 if imaOrFma(inst.Op) {
416 args[0], args[2] = args[2], args[0]
417 } else {
418 args[0], args[1], args[2] = args[2], args[0], args[1]
419 }
420 } else if len(args) == 2 {
421 args[0], args[1] = args[1], args[0]
422 }
423 }
424 }
425
426
427
428 if mask != "" {
429 args = append(args, mask)
430 }
431
432 if op == "" {
433 op = inst.Op.String()
434 }
435 op = strings.ToLower(op)
436
437 return op + " " + strings.Join(args, ",")
438 }
439
View as plain text