1
2
3
4
5 package riscv64asm
6
7 import (
8 "fmt"
9 "io"
10 "strconv"
11 "strings"
12 )
13
14
15
16
17
18
19
20
21
22
23
24 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
25 if symname == nil {
26 symname = func(uint64) (string, uint64) { return "", 0 }
27 }
28
29 hasVectorArg := false
30 var args []string
31 for _, a := range inst.Args {
32 if a == nil {
33 break
34 }
35 args = append(args, plan9Arg(&inst, pc, symname, a))
36 if r, ok := a.(Reg); ok {
37 hasVectorArg = hasVectorArg || (r >= V0 && r <= V31)
38 }
39 }
40
41 if hasVectorArg {
42 return plan9VectorOp(inst, args)
43 }
44
45 op := inst.Op.String()
46
47 goSyntaxSwitch:
48 switch inst.Op {
49
50 case AMOADD_D, AMOADD_D_AQ, AMOADD_D_RL, AMOADD_D_AQRL, AMOADD_W, AMOADD_W_AQ,
51 AMOADD_W_RL, AMOADD_W_AQRL, AMOAND_D, AMOAND_D_AQ, AMOAND_D_RL, AMOAND_D_AQRL,
52 AMOAND_W, AMOAND_W_AQ, AMOAND_W_RL, AMOAND_W_AQRL, AMOMAXU_D, AMOMAXU_D_AQ,
53 AMOMAXU_D_RL, AMOMAXU_D_AQRL, AMOMAXU_W, AMOMAXU_W_AQ, AMOMAXU_W_RL, AMOMAXU_W_AQRL,
54 AMOMAX_D, AMOMAX_D_AQ, AMOMAX_D_RL, AMOMAX_D_AQRL, AMOMAX_W, AMOMAX_W_AQ, AMOMAX_W_RL,
55 AMOMAX_W_AQRL, AMOMINU_D, AMOMINU_D_AQ, AMOMINU_D_RL, AMOMINU_D_AQRL, AMOMINU_W,
56 AMOMINU_W_AQ, AMOMINU_W_RL, AMOMINU_W_AQRL, AMOMIN_D, AMOMIN_D_AQ, AMOMIN_D_RL,
57 AMOMIN_D_AQRL, AMOMIN_W, AMOMIN_W_AQ, AMOMIN_W_RL, AMOMIN_W_AQRL, AMOOR_D, AMOOR_D_AQ,
58 AMOOR_D_RL, AMOOR_D_AQRL, AMOOR_W, AMOOR_W_AQ, AMOOR_W_RL, AMOOR_W_AQRL, AMOSWAP_D,
59 AMOSWAP_D_AQ, AMOSWAP_D_RL, AMOSWAP_D_AQRL, AMOSWAP_W, AMOSWAP_W_AQ, AMOSWAP_W_RL,
60 AMOSWAP_W_AQRL, AMOXOR_D, AMOXOR_D_AQ, AMOXOR_D_RL, AMOXOR_D_AQRL, AMOXOR_W,
61 AMOXOR_W_AQ, AMOXOR_W_RL, AMOXOR_W_AQRL, SC_D, SC_D_AQ, SC_D_RL, SC_D_AQRL,
62 SC_W, SC_W_AQ, SC_W_RL, SC_W_AQRL:
63
64 args[2], args[1] = args[1], args[2]
65
66 case ADDI:
67 if inst.Args[2].(Simm).Imm == 0 {
68 op = "MOV"
69 args = args[:len(args)-1]
70 }
71
72 case ADDIW:
73 if inst.Args[2].(Simm).Imm == 0 {
74 op = "MOVW"
75 args = args[:len(args)-1]
76 }
77
78 case ORI:
79 if inst.Args[0].(Reg) == X0 {
80 simm := inst.Args[2].(Simm)
81 switch simm.Imm & 0b11111 {
82 case 0:
83 op = "PREFETCHI"
84 case 1:
85 op = "PREFETCHR"
86 case 3:
87 op = "PREFETCHW"
88 default:
89 break goSyntaxSwitch
90 }
91
92 simm.Imm = simm.Imm &^ 0b11111
93 args[0] = plan9Arg(&inst, pc, symname, RegOffset{inst.Args[1].(Reg), simm})
94 args = args[:len(args)-2]
95 }
96
97 case ANDI:
98 if inst.Args[2].(Simm).Imm == 255 {
99 op = "MOVBU"
100 args = args[:len(args)-1]
101 }
102
103 case BEQ:
104 if inst.Args[1].(Reg) == X0 {
105 op = "BEQZ"
106 args[1] = args[2]
107 args = args[:len(args)-1]
108 }
109 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
110 args[i], args[j] = args[j], args[i]
111 }
112
113 case BGE:
114 if inst.Args[1].(Reg) == X0 {
115 op = "BGEZ"
116 args[1] = args[2]
117 args = args[:len(args)-1]
118 }
119 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
120 args[i], args[j] = args[j], args[i]
121 }
122
123 case BLT:
124 if inst.Args[1].(Reg) == X0 {
125 op = "BLTZ"
126 args[1] = args[2]
127 args = args[:len(args)-1]
128 }
129 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
130 args[i], args[j] = args[j], args[i]
131 }
132
133 case BNE:
134 if inst.Args[1].(Reg) == X0 {
135 op = "BNEZ"
136 args[1] = args[2]
137 args = args[:len(args)-1]
138 }
139 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
140 args[i], args[j] = args[j], args[i]
141 }
142
143 case BLTU, BGEU:
144 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
145 args[i], args[j] = args[j], args[i]
146 }
147
148 case CSRRW:
149 switch inst.Args[1].(CSR) {
150 case FCSR:
151 op = "FSCSR"
152 args[1] = args[2]
153 args = args[:len(args)-1]
154 case FFLAGS:
155 op = "FSFLAGS"
156 args[1] = args[2]
157 args = args[:len(args)-1]
158 case FRM:
159 op = "FSRM"
160 args[1] = args[2]
161 args = args[:len(args)-1]
162 case CYCLE:
163 if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
164 op = "UNIMP"
165 args = nil
166 }
167 }
168
169 case CSRRS:
170 if inst.Args[2].(Reg) == X0 {
171 switch inst.Args[1].(CSR) {
172 case FCSR:
173 op = "FRCSR"
174 args = args[:len(args)-2]
175 case FFLAGS:
176 op = "FRFLAGS"
177 args = args[:len(args)-2]
178 case FRM:
179 op = "FRRM"
180 args = args[:len(args)-2]
181 case CYCLE:
182 op = "RDCYCLE"
183 args = args[:len(args)-2]
184 case CYCLEH:
185 op = "RDCYCLEH"
186 args = args[:len(args)-2]
187 case INSTRET:
188 op = "RDINSTRET"
189 args = args[:len(args)-2]
190 case INSTRETH:
191 op = "RDINSTRETH"
192 args = args[:len(args)-2]
193 case TIME:
194 op = "RDTIME"
195 args = args[:len(args)-2]
196 case TIMEH:
197 op = "RDTIMEH"
198 args = args[:len(args)-2]
199 }
200 }
201
202 case FENCE:
203 fm := inst.Enc >> 28
204 pred := inst.Args[0].(MemOrder).String()
205 succ := inst.Args[1].(MemOrder).String()
206 if fm == 0b1000 {
207 if pred == "rw" && succ == "rw" {
208 return "FENCE.TSO"
209 }
210 return op
211 }
212
213 if pred == "w" && succ == "" {
214 return "PAUSE"
215 }
216 if fm != 0 || pred == "" || succ == "" || (pred == "iorw" && succ == "iorw") {
217
218
219 return op
220 }
221 args[0], args[1] = args[1], args[0]
222
223 case FMADD_D, FMADD_H, FMADD_Q, FMADD_S, FMSUB_D, FMSUB_H,
224 FMSUB_Q, FMSUB_S, FNMADD_D, FNMADD_H, FNMADD_Q, FNMADD_S,
225 FNMSUB_D, FNMSUB_H, FNMSUB_Q, FNMSUB_S:
226 args[1], args[3] = args[3], args[1]
227
228 case FMV_W_X:
229 if inst.Args[1].(Reg) == X0 {
230 args[1] = "$(0.0)"
231 }
232 fallthrough
233 case FMV_X_W:
234 op = "MOVF"
235
236 case FMV_D_X:
237 if inst.Args[1].(Reg) == X0 {
238 args[1] = "$(0.0)"
239 }
240 fallthrough
241 case FMV_X_D:
242 op = "MOVD"
243
244 case FSGNJ_S:
245 if inst.Args[2] == inst.Args[1] {
246 op = "MOVF"
247 args = args[:len(args)-1]
248 }
249
250 case FSGNJ_D:
251 if inst.Args[2] == inst.Args[1] {
252 op = "MOVD"
253 args = args[:len(args)-1]
254 }
255
256 case FSGNJX_S:
257 if inst.Args[2] == inst.Args[1] {
258 op = "FABSS"
259 args = args[:len(args)-1]
260 }
261
262 case FSGNJX_D:
263 if inst.Args[2] == inst.Args[1] {
264 op = "FABSD"
265 args = args[:len(args)-1]
266 }
267
268 case FSGNJN_S:
269 if inst.Args[2] == inst.Args[1] {
270 op = "FNEGS"
271 args = args[:len(args)-1]
272 }
273
274 case FSGNJN_D:
275 if inst.Args[2] == inst.Args[1] {
276 op = "FNESD"
277 args = args[:len(args)-1]
278 }
279
280 case LD, SD:
281 op = "MOV"
282 if inst.Op == SD {
283 args[0], args[1] = args[1], args[0]
284 }
285
286 case LB, SB:
287 op = "MOVB"
288 if inst.Op == SB {
289 args[0], args[1] = args[1], args[0]
290 }
291
292 case LH, SH:
293 op = "MOVH"
294 if inst.Op == SH {
295 args[0], args[1] = args[1], args[0]
296 }
297
298 case LW, SW:
299 op = "MOVW"
300 if inst.Op == SW {
301 args[0], args[1] = args[1], args[0]
302 }
303
304 case LBU:
305 op = "MOVBU"
306
307 case LHU:
308 op = "MOVHU"
309
310 case LWU:
311 op = "MOVWU"
312
313 case FLW, FSW:
314 op = "MOVF"
315 if inst.Op == FSW {
316 args[0], args[1] = args[1], args[0]
317 }
318
319 case FLD, FSD:
320 op = "MOVD"
321 if inst.Op == FSD {
322 args[0], args[1] = args[1], args[0]
323 }
324
325 case SUB:
326 if inst.Args[1].(Reg) == X0 {
327 op = "NEG"
328 args[1] = args[2]
329 args = args[:len(args)-1]
330 }
331
332 case XORI:
333 if inst.Args[2].(Simm).String() == "-1" {
334 op = "NOT"
335 args = args[:len(args)-1]
336 }
337
338 case SLTIU:
339 if inst.Args[2].(Simm).Imm == 1 {
340 op = "SEQZ"
341 args = args[:len(args)-1]
342 }
343
344 case SLTU:
345 if inst.Args[1].(Reg) == X0 {
346 op = "SNEZ"
347 args[1] = args[2]
348 args = args[:len(args)-1]
349 }
350
351 case JAL:
352 if inst.Args[0].(Reg) == X0 {
353 op = "JMP"
354 args[0] = args[1]
355 args = args[:len(args)-1]
356 } else if inst.Args[0].(Reg) == X1 {
357 op = "CALL"
358 args[0] = args[1]
359 args = args[:len(args)-1]
360 } else {
361 args[0], args[1] = args[1], args[0]
362 }
363
364 case JALR:
365 if inst.Args[0].(Reg) == X0 {
366 if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
367 op = "RET"
368 args = nil
369 break
370 }
371 op = "JMP"
372 args[0] = args[1]
373 args = args[:len(args)-1]
374 } else if inst.Args[0].(Reg) == X1 {
375 op = "CALL"
376 args[0] = args[1]
377 args = args[:len(args)-1]
378 } else {
379 args[0], args[1] = args[1], args[0]
380 }
381
382 case VSETVLI, VSETIVLI:
383 args[0], args[1], args[2] = args[2], args[0], args[1]
384
385 case VSETVL:
386 args[0], args[2] = args[2], args[0]
387 }
388
389
390 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
391 args[i], args[j] = args[j], args[i]
392 }
393
394
395
396 op = strings.Replace(op, ".AQRL", "", -1)
397 op = strings.Replace(op, ".AQ", "", -1)
398 op = strings.Replace(op, ".RL", "", -1)
399 op = strings.Replace(op, ".", "", -1)
400
401 if args != nil {
402 op += " " + strings.Join(args, ", ")
403 }
404
405 return op
406 }
407
408 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
409 switch a := arg.(type) {
410 case Uimm:
411 return fmt.Sprintf("$%d", uint32(a.Imm))
412
413 case Simm:
414 imm, _ := strconv.Atoi(a.String())
415 if a.Width == 13 || a.Width == 21 {
416 addr := int64(pc) + int64(imm)
417 if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
418 return fmt.Sprintf("%s(SB)", s)
419 }
420 return fmt.Sprintf("%d(PC)", imm/4)
421 }
422 return fmt.Sprintf("$%d", int32(imm))
423
424 case RegOffset:
425 if a.Ofs.Imm == 0 {
426 return fmt.Sprintf("(X%d)", a.OfsReg)
427 } else {
428 return fmt.Sprintf("%s(X%d)", a.Ofs.String(), a.OfsReg)
429 }
430
431 case RegPtr:
432 return fmt.Sprintf("(X%d)", a.reg)
433
434 default:
435 return strings.ToUpper(arg.String())
436 }
437 }
438
439 func plan9VectorOp(inst Inst, args []string) string {
440
441
442
443
444 var op string
445 rawArgs := inst.Args[:]
446
447 var mask string
448 if inst.Enc&(1<<25) == 0 {
449 mask = "V0"
450 if !implicitMask(inst.Op) {
451 args = args[1:]
452 rawArgs = rawArgs[1:]
453 }
454 }
455
456 if len(args) > 1 {
457 if inst.Enc&0x7f == 0x7 {
458
459 if len(args) == 3 {
460 args[0], args[1] = args[1], args[0]
461 }
462 op = pseudoRVVLoad(inst.Op)
463 } else if inst.Enc&0x7f == 0x27 {
464
465 if len(args) == 3 {
466 args[0], args[1], args[2] = args[2], args[0], args[1]
467 } else if len(args) == 2 {
468 args[0], args[1] = args[1], args[0]
469 }
470 } else {
471
472
473 op, args = pseudoRVVArith(inst.Op, rawArgs, args)
474
475 if len(args) == 3 && !imaOrFma(inst.Op) {
476 args[0], args[1] = args[1], args[0]
477 }
478 }
479 }
480
481
482
483 if mask != "" {
484 args = append(args[:len(args)-1], mask, args[len(args)-1])
485 }
486
487 if op == "" {
488 op = inst.Op.String()
489 }
490
491 op = strings.Replace(op, ".", "", -1)
492 return op + " " + strings.Join(args, ", ")
493 }
494
View as plain text