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