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 var args []string
30 for _, a := range inst.Args {
31 if a == nil {
32 break
33 }
34 args = append(args, plan9Arg(&inst, pc, symname, a))
35 }
36
37 op := inst.Op.String()
38
39 switch inst.Op {
40
41 case AMOADD_D, AMOADD_D_AQ, AMOADD_D_RL, AMOADD_D_AQRL, AMOADD_W, AMOADD_W_AQ,
42 AMOADD_W_RL, AMOADD_W_AQRL, AMOAND_D, AMOAND_D_AQ, AMOAND_D_RL, AMOAND_D_AQRL,
43 AMOAND_W, AMOAND_W_AQ, AMOAND_W_RL, AMOAND_W_AQRL, AMOMAXU_D, AMOMAXU_D_AQ,
44 AMOMAXU_D_RL, AMOMAXU_D_AQRL, AMOMAXU_W, AMOMAXU_W_AQ, AMOMAXU_W_RL, AMOMAXU_W_AQRL,
45 AMOMAX_D, AMOMAX_D_AQ, AMOMAX_D_RL, AMOMAX_D_AQRL, AMOMAX_W, AMOMAX_W_AQ, AMOMAX_W_RL,
46 AMOMAX_W_AQRL, AMOMINU_D, AMOMINU_D_AQ, AMOMINU_D_RL, AMOMINU_D_AQRL, AMOMINU_W,
47 AMOMINU_W_AQ, AMOMINU_W_RL, AMOMINU_W_AQRL, AMOMIN_D, AMOMIN_D_AQ, AMOMIN_D_RL,
48 AMOMIN_D_AQRL, AMOMIN_W, AMOMIN_W_AQ, AMOMIN_W_RL, AMOMIN_W_AQRL, AMOOR_D, AMOOR_D_AQ,
49 AMOOR_D_RL, AMOOR_D_AQRL, AMOOR_W, AMOOR_W_AQ, AMOOR_W_RL, AMOOR_W_AQRL, AMOSWAP_D,
50 AMOSWAP_D_AQ, AMOSWAP_D_RL, AMOSWAP_D_AQRL, AMOSWAP_W, AMOSWAP_W_AQ, AMOSWAP_W_RL,
51 AMOSWAP_W_AQRL, AMOXOR_D, AMOXOR_D_AQ, AMOXOR_D_RL, AMOXOR_D_AQRL, AMOXOR_W,
52 AMOXOR_W_AQ, AMOXOR_W_RL, AMOXOR_W_AQRL, SC_D, SC_D_AQ, SC_D_RL, SC_D_AQRL,
53 SC_W, SC_W_AQ, SC_W_RL, SC_W_AQRL:
54
55 args[2], args[1] = args[1], args[2]
56
57 case ADDI:
58 if inst.Args[2].(Simm).Imm == 0 {
59 op = "MOV"
60 args = args[:len(args)-1]
61 }
62
63 case ADDIW:
64 if inst.Args[2].(Simm).Imm == 0 {
65 op = "MOVW"
66 args = args[:len(args)-1]
67 }
68
69 case ANDI:
70 if inst.Args[2].(Simm).Imm == 255 {
71 op = "MOVBU"
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 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
82 args[i], args[j] = args[j], args[i]
83 }
84
85 case BGE:
86 if inst.Args[1].(Reg) == X0 {
87 op = "BGEZ"
88 args[1] = args[2]
89 args = args[:len(args)-1]
90 }
91 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
92 args[i], args[j] = args[j], args[i]
93 }
94
95 case BLT:
96 if inst.Args[1].(Reg) == X0 {
97 op = "BLTZ"
98 args[1] = args[2]
99 args = args[:len(args)-1]
100 }
101 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
102 args[i], args[j] = args[j], args[i]
103 }
104
105 case BNE:
106 if inst.Args[1].(Reg) == X0 {
107 op = "BNEZ"
108 args[1] = args[2]
109 args = args[:len(args)-1]
110 }
111 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
112 args[i], args[j] = args[j], args[i]
113 }
114
115 case BLTU, BGEU:
116 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
117 args[i], args[j] = args[j], args[i]
118 }
119
120 case CSRRW:
121 switch inst.Args[1].(CSR) {
122 case FCSR:
123 op = "FSCSR"
124 args[1] = args[2]
125 args = args[:len(args)-1]
126 case FFLAGS:
127 op = "FSFLAGS"
128 args[1] = args[2]
129 args = args[:len(args)-1]
130 case FRM:
131 op = "FSRM"
132 args[1] = args[2]
133 args = args[:len(args)-1]
134 case CYCLE:
135 if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
136 op = "UNIMP"
137 args = nil
138 }
139 }
140
141 case CSRRS:
142 if inst.Args[2].(Reg) == X0 {
143 switch inst.Args[1].(CSR) {
144 case FCSR:
145 op = "FRCSR"
146 args = args[:len(args)-2]
147 case FFLAGS:
148 op = "FRFLAGS"
149 args = args[:len(args)-2]
150 case FRM:
151 op = "FRRM"
152 args = args[:len(args)-2]
153 case CYCLE:
154 op = "RDCYCLE"
155 args = args[:len(args)-2]
156 case CYCLEH:
157 op = "RDCYCLEH"
158 args = args[:len(args)-2]
159 case INSTRET:
160 op = "RDINSTRET"
161 args = args[:len(args)-2]
162 case INSTRETH:
163 op = "RDINSTRETH"
164 args = args[:len(args)-2]
165 case TIME:
166 op = "RDTIME"
167 args = args[:len(args)-2]
168 case TIMEH:
169 op = "RDTIMEH"
170 args = args[:len(args)-2]
171 }
172 }
173
174
175 case FENCE:
176 args = nil
177
178 case FMADD_D, FMADD_H, FMADD_Q, FMADD_S, FMSUB_D, FMSUB_H,
179 FMSUB_Q, FMSUB_S, FNMADD_D, FNMADD_H, FNMADD_Q, FNMADD_S,
180 FNMSUB_D, FNMSUB_H, FNMSUB_Q, FNMSUB_S:
181 args[1], args[3] = args[3], args[1]
182
183 case FSGNJ_S:
184 if inst.Args[2] == inst.Args[1] {
185 op = "MOVF"
186 args = args[:len(args)-1]
187 }
188
189 case FSGNJ_D:
190 if inst.Args[2] == inst.Args[1] {
191 op = "MOVD"
192 args = args[:len(args)-1]
193 }
194
195 case FSGNJX_S:
196 if inst.Args[2] == inst.Args[1] {
197 op = "FABSS"
198 args = args[:len(args)-1]
199 }
200
201 case FSGNJX_D:
202 if inst.Args[2] == inst.Args[1] {
203 op = "FABSD"
204 args = args[:len(args)-1]
205 }
206
207 case FSGNJN_S:
208 if inst.Args[2] == inst.Args[1] {
209 op = "FNEGS"
210 args = args[:len(args)-1]
211 }
212
213 case FSGNJN_D:
214 if inst.Args[2] == inst.Args[1] {
215 op = "FNESD"
216 args = args[:len(args)-1]
217 }
218
219 case LD, SD:
220 op = "MOV"
221 if inst.Op == SD {
222 args[0], args[1] = args[1], args[0]
223 }
224
225 case LB, SB:
226 op = "MOVB"
227 if inst.Op == SB {
228 args[0], args[1] = args[1], args[0]
229 }
230
231 case LH, SH:
232 op = "MOVH"
233 if inst.Op == SH {
234 args[0], args[1] = args[1], args[0]
235 }
236
237 case LW, SW:
238 op = "MOVW"
239 if inst.Op == SW {
240 args[0], args[1] = args[1], args[0]
241 }
242
243 case LBU:
244 op = "MOVBU"
245
246 case LHU:
247 op = "MOVHU"
248
249 case LWU:
250 op = "MOVWU"
251
252 case FLW, FSW:
253 op = "MOVF"
254 if inst.Op == FLW {
255 args[0], args[1] = args[1], args[0]
256 }
257
258 case FLD, FSD:
259 op = "MOVD"
260 if inst.Op == FLD {
261 args[0], args[1] = args[1], args[0]
262 }
263
264 case SUB:
265 if inst.Args[1].(Reg) == X0 {
266 op = "NEG"
267 args[1] = args[2]
268 args = args[:len(args)-1]
269 }
270
271 case XORI:
272 if inst.Args[2].(Simm).String() == "-1" {
273 op = "NOT"
274 args = args[:len(args)-1]
275 }
276
277 case SLTIU:
278 if inst.Args[2].(Simm).Imm == 1 {
279 op = "SEQZ"
280 args = args[:len(args)-1]
281 }
282
283 case SLTU:
284 if inst.Args[1].(Reg) == X0 {
285 op = "SNEZ"
286 args[1] = args[2]
287 args = args[:len(args)-1]
288 }
289
290 case JAL:
291 if inst.Args[0].(Reg) == X0 {
292 op = "JMP"
293 args[0] = args[1]
294 args = args[:len(args)-1]
295 } else if inst.Args[0].(Reg) == X1 {
296 op = "CALL"
297 args[0] = args[1]
298 args = args[:len(args)-1]
299 } else {
300 args[0], args[1] = args[1], args[0]
301 }
302
303 case JALR:
304 if inst.Args[0].(Reg) == X0 {
305 if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
306 op = "RET"
307 args = nil
308 break
309 }
310 op = "JMP"
311 args[0] = args[1]
312 args = args[:len(args)-1]
313 } else if inst.Args[0].(Reg) == X1 {
314 op = "CALL"
315 args[0] = args[1]
316 args = args[:len(args)-1]
317 } else {
318 args[0], args[1] = args[1], args[0]
319 }
320 }
321
322
323 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
324 args[i], args[j] = args[j], args[i]
325 }
326
327
328
329 op = strings.Replace(op, ".AQRL", "", -1)
330 op = strings.Replace(op, ".AQ", "", -1)
331 op = strings.Replace(op, ".RL", "", -1)
332 op = strings.Replace(op, ".", "", -1)
333
334 if args != nil {
335 op += " " + strings.Join(args, ", ")
336 }
337
338 return op
339 }
340
341 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
342 switch a := arg.(type) {
343 case Uimm:
344 return fmt.Sprintf("$%d", uint32(a.Imm))
345
346 case Simm:
347 imm, _ := strconv.Atoi(a.String())
348 if a.Width == 13 || a.Width == 21 {
349 addr := int64(pc) + int64(imm)
350 if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
351 return fmt.Sprintf("%s(SB)", s)
352 }
353 return fmt.Sprintf("%d(PC)", imm/4)
354 }
355 return fmt.Sprintf("$%d", int32(imm))
356
357 case Reg:
358 if a <= 31 {
359 return fmt.Sprintf("X%d", a)
360 } else {
361 return fmt.Sprintf("F%d", a-32)
362 }
363
364 case RegOffset:
365 if a.Ofs.Imm == 0 {
366 return fmt.Sprintf("(X%d)", a.OfsReg)
367 } else {
368 return fmt.Sprintf("%s(X%d)", a.Ofs.String(), a.OfsReg)
369 }
370
371 case AmoReg:
372 return fmt.Sprintf("(X%d)", a.reg)
373
374 default:
375 return strings.ToUpper(arg.String())
376 }
377 }
378
View as plain text