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