1
2
3
4
5 package armasm
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "fmt"
11 "io"
12 "math"
13 "strings"
14 )
15
16
17
18
19
20
21
22
23
24
25 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
26 if symname == nil {
27 symname = func(uint64) (string, uint64) { return "", 0 }
28 }
29
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 }
37
38 op := inst.Op.String()
39
40 switch inst.Op &^ 15 {
41 case LDR_EQ, LDRB_EQ, LDRH_EQ, LDRSB_EQ, LDRSH_EQ, VLDR_EQ:
42
43 reg, _ := inst.Args[0].(Reg)
44 mem, _ := inst.Args[1].(Mem)
45 if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
46 return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
47 }
48
49
50 if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
51 addr := uint32(pc) + 8 + uint32(mem.Offset)
52 buf := make([]byte, 8)
53 switch inst.Op &^ 15 {
54 case LDRB_EQ, LDRSB_EQ:
55 if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
56 break
57 }
58 args[1] = fmt.Sprintf("$%#x", buf[0])
59
60 case LDRH_EQ, LDRSH_EQ:
61 if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
62 break
63 }
64 args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
65
66 case LDR_EQ:
67 if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
68 break
69 }
70 x := binary.LittleEndian.Uint32(buf)
71 if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
72 args[1] = fmt.Sprintf("$%s(SB)", s)
73 } else {
74 args[1] = fmt.Sprintf("$%#x", x)
75 }
76
77 case VLDR_EQ:
78 switch {
79 case strings.HasPrefix(args[0], "D"):
80 if _, err := text.ReadAt(buf, int64(addr)); err != nil {
81 break
82 }
83 args[1] = fmt.Sprintf("$%f", math.Float64frombits(binary.LittleEndian.Uint64(buf)))
84 case strings.HasPrefix(args[0], "S"):
85 if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
86 break
87 }
88 args[1] = fmt.Sprintf("$%f", math.Float32frombits(binary.LittleEndian.Uint32(buf)))
89 default:
90 panic(fmt.Sprintf("wrong FP register: %v", inst))
91 }
92 }
93 }
94 }
95
96
97 suffix := ""
98 switch inst.Op &^ 15 {
99 case PLD, PLI, PLD_W:
100 if mem, ok := inst.Args[0].(Mem); ok {
101 args[0], suffix = memOpTrans(mem)
102 } else {
103 panic(fmt.Sprintf("illegal instruction: %v", inst))
104 }
105 case LDR_EQ, LDRB_EQ, LDRSB_EQ, LDRH_EQ, LDRSH_EQ, STR_EQ, STRB_EQ, STRH_EQ, VLDR_EQ, VSTR_EQ, LDREX_EQ, LDREXH_EQ, LDREXB_EQ:
106 if mem, ok := inst.Args[1].(Mem); ok {
107 args[1], suffix = memOpTrans(mem)
108 } else {
109 panic(fmt.Sprintf("illegal instruction: %v", inst))
110 }
111 case SWP_EQ, SWP_B_EQ, STREX_EQ, STREXB_EQ, STREXH_EQ:
112 if mem, ok := inst.Args[2].(Mem); ok {
113 args[2], suffix = memOpTrans(mem)
114 } else {
115 panic(fmt.Sprintf("illegal instruction: %v", inst))
116 }
117 }
118
119
120 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
121 args[i], args[j] = args[j], args[i]
122 }
123
124 switch inst.Op &^ 15 {
125 case SMLAWT_EQ, SMLAWB_EQ, MLA_EQ, MLA_S_EQ, MLS_EQ, SMMLA_EQ, SMMLS_EQ, SMLABB_EQ, SMLATB_EQ, SMLABT_EQ, SMLATT_EQ, SMLAD_EQ, SMLAD_X_EQ, SMLSD_EQ, SMLSD_X_EQ:
126 args = []string{args[1], args[2], args[0], args[3]}
127 }
128
129 switch inst.Op &^ 15 {
130 case STREX_EQ, STREXB_EQ, STREXH_EQ, SWP_EQ, SWP_B_EQ:
131 args = []string{args[1], args[0], args[2]}
132 }
133
134
135 op, args = fpTrans(&inst, op, args)
136
137
138 switch inst.Op &^ 15 {
139 case MOV_EQ:
140 op = "MOVW" + op[3:]
141 case LDR_EQ, MSR_EQ, MRS_EQ:
142 op = "MOVW" + op[3:] + suffix
143 case VMRS_EQ, VMSR_EQ:
144 op = "MOVW" + op[4:] + suffix
145 case LDRB_EQ, UXTB_EQ:
146 op = "MOVBU" + op[4:] + suffix
147 case LDRSB_EQ:
148 op = "MOVBS" + op[5:] + suffix
149 case SXTB_EQ:
150 op = "MOVBS" + op[4:] + suffix
151 case LDRH_EQ, UXTH_EQ:
152 op = "MOVHU" + op[4:] + suffix
153 case LDRSH_EQ:
154 op = "MOVHS" + op[5:] + suffix
155 case SXTH_EQ:
156 op = "MOVHS" + op[4:] + suffix
157 case STR_EQ:
158 op = "MOVW" + op[3:] + suffix
159 args[0], args[1] = args[1], args[0]
160 case STRB_EQ:
161 op = "MOVB" + op[4:] + suffix
162 args[0], args[1] = args[1], args[0]
163 case STRH_EQ:
164 op = "MOVH" + op[4:] + suffix
165 args[0], args[1] = args[1], args[0]
166 case VSTR_EQ:
167 args[0], args[1] = args[1], args[0]
168 default:
169 op = op + suffix
170 }
171
172 if args != nil {
173 op += " " + strings.Join(args, ", ")
174 }
175
176 return op
177 }
178
179
180
181
182
183 var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
184
185 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
186 switch a := arg.(type) {
187 case Endian:
188
189 case Imm:
190 return fmt.Sprintf("$%d", uint32(a))
191
192 case Mem:
193
194 case PCRel:
195 addr := uint32(pc) + 8 + uint32(a)
196 if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
197 return fmt.Sprintf("%s(SB)", s)
198 }
199 return fmt.Sprintf("%#x", addr)
200
201 case Reg:
202 if a < 16 {
203 return fmt.Sprintf("R%d", int(a))
204 }
205
206 case RegList:
207 var buf bytes.Buffer
208 start := -2
209 end := -2
210 fmt.Fprintf(&buf, "[")
211 flush := func() {
212 if start >= 0 {
213 if buf.Len() > 1 {
214 fmt.Fprintf(&buf, ",")
215 }
216 if start == end {
217 fmt.Fprintf(&buf, "R%d", start)
218 } else {
219 fmt.Fprintf(&buf, "R%d-R%d", start, end)
220 }
221 start = -2
222 end = -2
223 }
224 }
225 for i := 0; i < 16; i++ {
226 if a&(1<<uint(i)) != 0 {
227 if i == end+1 {
228 end++
229 continue
230 }
231 start = i
232 end = i
233 } else {
234 flush()
235 }
236 }
237 flush()
238 fmt.Fprintf(&buf, "]")
239 return buf.String()
240
241 case RegShift:
242 return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
243
244 case RegShiftReg:
245 return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
246 }
247 return strings.ToUpper(arg.String())
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 func memOpTrans(mem Mem) (string, string) {
264 suffix := ""
265 switch mem.Mode {
266 case AddrOffset, AddrLDM:
267
268 case AddrPreIndex, AddrLDM_WB:
269 suffix = ".W"
270 case AddrPostIndex:
271 suffix = ".P"
272 }
273 off := ""
274 if mem.Offset != 0 {
275 off = fmt.Sprintf("%#x", mem.Offset)
276 }
277 base := fmt.Sprintf("(R%d)", int(mem.Base))
278 index := ""
279 if mem.Sign != 0 {
280 sign := ""
281 if mem.Sign < 0 {
282 suffix += ".U"
283 }
284 shift := ""
285 if mem.Count != 0 {
286 shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
287 }
288 index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
289 }
290 return off + base + index, suffix
291 }
292
293 type goFPInfo struct {
294 op Op
295 transArgs []int
296 gnuName string
297 goName string
298 }
299
300 var fpInst []goFPInfo = []goFPInfo{
301 {VADD_EQ_F32, []int{2, 1, 0}, "VADD", "ADDF"},
302 {VADD_EQ_F64, []int{2, 1, 0}, "VADD", "ADDD"},
303 {VSUB_EQ_F32, []int{2, 1, 0}, "VSUB", "SUBF"},
304 {VSUB_EQ_F64, []int{2, 1, 0}, "VSUB", "SUBD"},
305 {VMUL_EQ_F32, []int{2, 1, 0}, "VMUL", "MULF"},
306 {VMUL_EQ_F64, []int{2, 1, 0}, "VMUL", "MULD"},
307 {VNMUL_EQ_F32, []int{2, 1, 0}, "VNMUL", "NMULF"},
308 {VNMUL_EQ_F64, []int{2, 1, 0}, "VNMUL", "NMULD"},
309 {VMLA_EQ_F32, []int{2, 1, 0}, "VMLA", "MULAF"},
310 {VMLA_EQ_F64, []int{2, 1, 0}, "VMLA", "MULAD"},
311 {VMLS_EQ_F32, []int{2, 1, 0}, "VMLS", "MULSF"},
312 {VMLS_EQ_F64, []int{2, 1, 0}, "VMLS", "MULSD"},
313 {VNMLA_EQ_F32, []int{2, 1, 0}, "VNMLA", "NMULAF"},
314 {VNMLA_EQ_F64, []int{2, 1, 0}, "VNMLA", "NMULAD"},
315 {VNMLS_EQ_F32, []int{2, 1, 0}, "VNMLS", "NMULSF"},
316 {VNMLS_EQ_F64, []int{2, 1, 0}, "VNMLS", "NMULSD"},
317 {VDIV_EQ_F32, []int{2, 1, 0}, "VDIV", "DIVF"},
318 {VDIV_EQ_F64, []int{2, 1, 0}, "VDIV", "DIVD"},
319 {VNEG_EQ_F32, []int{1, 0}, "VNEG", "NEGF"},
320 {VNEG_EQ_F64, []int{1, 0}, "VNEG", "NEGD"},
321 {VABS_EQ_F32, []int{1, 0}, "VABS", "ABSF"},
322 {VABS_EQ_F64, []int{1, 0}, "VABS", "ABSD"},
323 {VSQRT_EQ_F32, []int{1, 0}, "VSQRT", "SQRTF"},
324 {VSQRT_EQ_F64, []int{1, 0}, "VSQRT", "SQRTD"},
325 {VCMP_EQ_F32, []int{1, 0}, "VCMP", "CMPF"},
326 {VCMP_EQ_F64, []int{1, 0}, "VCMP", "CMPD"},
327 {VCMP_E_EQ_F32, []int{1, 0}, "VCMP.E", "CMPF"},
328 {VCMP_E_EQ_F64, []int{1, 0}, "VCMP.E", "CMPD"},
329 {VLDR_EQ, []int{1}, "VLDR", "MOV"},
330 {VSTR_EQ, []int{1}, "VSTR", "MOV"},
331 {VMOV_EQ_F32, []int{1, 0}, "VMOV", "MOVF"},
332 {VMOV_EQ_F64, []int{1, 0}, "VMOV", "MOVD"},
333 {VMOV_EQ_32, []int{1, 0}, "VMOV", "MOVW"},
334 {VMOV_EQ, []int{1, 0}, "VMOV", "MOVW"},
335 {VCVT_EQ_F64_F32, []int{1, 0}, "VCVT", "MOVFD"},
336 {VCVT_EQ_F32_F64, []int{1, 0}, "VCVT", "MOVDF"},
337 {VCVT_EQ_F32_U32, []int{1, 0}, "VCVT", "MOVWF.U"},
338 {VCVT_EQ_F32_S32, []int{1, 0}, "VCVT", "MOVWF"},
339 {VCVT_EQ_S32_F32, []int{1, 0}, "VCVT", "MOVFW"},
340 {VCVT_EQ_U32_F32, []int{1, 0}, "VCVT", "MOVFW.U"},
341 {VCVT_EQ_F64_U32, []int{1, 0}, "VCVT", "MOVWD.U"},
342 {VCVT_EQ_F64_S32, []int{1, 0}, "VCVT", "MOVWD"},
343 {VCVT_EQ_S32_F64, []int{1, 0}, "VCVT", "MOVDW"},
344 {VCVT_EQ_U32_F64, []int{1, 0}, "VCVT", "MOVDW.U"},
345 }
346
347
348
349
350
351
352
353 func fpTrans(inst *Inst, op string, args []string) (string, []string) {
354 for _, fp := range fpInst {
355 if inst.Op&^15 == fp.op {
356
357 op = strings.Replace(op, ".F32", "", -1)
358 op = strings.Replace(op, ".F64", "", -1)
359 op = strings.Replace(op, ".S32", "", -1)
360 op = strings.Replace(op, ".U32", "", -1)
361 op = strings.Replace(op, ".32", "", -1)
362
363 if fp.op == VLDR_EQ || fp.op == VSTR_EQ {
364 switch {
365 case strings.HasPrefix(args[fp.transArgs[0]], "D"):
366 op = "MOVD" + op[len(fp.gnuName):]
367 case strings.HasPrefix(args[fp.transArgs[0]], "S"):
368 op = "MOVF" + op[len(fp.gnuName):]
369 default:
370 panic(fmt.Sprintf("wrong FP register: %v", inst))
371 }
372 } else {
373 op = fp.goName + op[len(fp.gnuName):]
374 }
375
376 for ix, ri := range fp.transArgs {
377 switch {
378 case strings.HasSuffix(args[ri], "[1]"):
379 break
380 case strings.HasSuffix(args[ri], "[0]"):
381 args[ri] = strings.Replace(args[ri], "[0]", "", -1)
382 fallthrough
383 case strings.HasPrefix(args[ri], "D"):
384 args[ri] = "F" + args[ri][1:]
385 case strings.HasPrefix(args[ri], "S"):
386 if inst.Args[ix].(Reg)&1 == 0 {
387 args[ri] = fmt.Sprintf("F%d", (inst.Args[ix].(Reg)-S0)/2)
388 }
389 case strings.HasPrefix(args[ri], "$"):
390 break
391 case strings.HasPrefix(args[ri], "R"):
392 break
393 default:
394 panic(fmt.Sprintf("wrong FP register: %v", inst))
395 }
396 }
397 break
398 }
399 }
400 return op, args
401 }
402
View as plain text