1
2
3
4
5 package ppc64asm
6
7 import (
8 "fmt"
9 "strings"
10 )
11
12
13
14
15
16
17
18 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
19 if symname == nil {
20 symname = func(uint64) (string, uint64) { return "", 0 }
21 }
22 if inst.Op == 0 && inst.Enc == 0 {
23 return "WORD $0"
24 } else if inst.Op == 0 {
25 return "?"
26 }
27 var args []string
28 for i, a := range inst.Args[:] {
29 if a == nil {
30 break
31 }
32 if s := plan9Arg(&inst, i, pc, a, symname); s != "" {
33 args = append(args, s)
34 }
35 }
36 var op string
37 op = plan9OpMap[inst.Op]
38 if op == "" {
39 op = strings.ToUpper(inst.Op.String())
40 if op[len(op)-1] == '.' {
41 op = op[:len(op)-1] + "CC"
42 }
43 }
44
45 switch inst.Op {
46 default:
47 switch len(args) {
48 case 0:
49 return op
50 case 1:
51 return fmt.Sprintf("%s %s", op, args[0])
52 case 2:
53 if inst.Op == COPY || inst.Op == PASTECC {
54 return op + " " + args[0] + "," + args[1]
55 }
56 return op + " " + args[1] + "," + args[0]
57 case 3:
58 if reverseOperandOrder(inst.Op) {
59 return op + " " + args[2] + "," + args[1] + "," + args[0]
60 }
61 case 4:
62 if reverseMiddleOps(inst.Op) {
63 return op + " " + args[1] + "," + args[3] + "," + args[2] + "," + args[0]
64 }
65 }
66 args = append(args, args[0])
67 return op + " " + strings.Join(args[1:], ",")
68 case PASTECC:
69
70 return op + " " + args[0] + "," + args[1] + "," + args[2]
71 case SYNC:
72 if args[0] == "$1" {
73 return "LWSYNC"
74 }
75 return "HWSYNC"
76
77 case ISEL:
78 return "ISEL " + args[3] + "," + args[1] + "," + args[2] + "," + args[0]
79
80
81
82 case STB, STBU,
83 STH, STHU,
84 STW, STWU,
85 STD, STDU,
86 STFD, STFDU,
87 STFS, STFSU,
88 STQ, HASHST, HASHSTP:
89 return op + " " + strings.Join(args, ",")
90
91 case FCMPU, FCMPO, CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI:
92 crf := int(inst.Args[0].(CondReg) - CR0)
93 cmpstr := op + " " + args[1] + "," + args[2]
94 if crf != 0 {
95 cmpstr += "," + args[0]
96 }
97 return cmpstr
98
99 case LIS:
100 return "ADDIS $0," + args[1] + "," + args[0]
101
102 case STBX, STBUX, STHX, STHUX, STWX, STWUX, STDX, STDUX,
103 STHBRX, STWBRX, STDBRX, STSWX, STFIWX:
104 return "MOV" + op[2:len(op)-1] + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
105
106 case STDCXCC, STWCXCC, STHCXCC, STBCXCC:
107 return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
108
109 case STXVX, STXVD2X, STXVW4X, STXVH8X, STXVB16X, STXSDX, STVX, STVXL, STVEBX, STVEHX, STVEWX, STXSIWX, STFDX, STFDUX, STFDPX, STFSX, STFSUX:
110 return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
111
112 case STXV:
113 return op + " " + args[0] + "," + args[1]
114
115 case STXVL, STXVLL:
116 return op + " " + args[0] + "," + args[1] + "," + args[2]
117
118 case LWAX, LWAUX, LWZX, LHZX, LBZX, LDX, LHAX, LHAUX, LDARX, LWARX, LHARX, LBARX, LFDX, LFDUX, LFSX, LFSUX, LDBRX, LWBRX, LHBRX, LDUX, LWZUX, LHZUX, LBZUX:
119 if args[1] == "0" {
120 return op + " (" + args[2] + ")," + args[0]
121 }
122 return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
123
124 case LXVX, LXVD2X, LXVW4X, LXVH8X, LXVB16X, LVX, LVXL, LVSR, LVSL, LVEBX, LVEHX, LVEWX, LXSDX, LXSIWAX:
125 return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
126
127 case LXV:
128 return op + " " + args[1] + "," + args[0]
129
130 case LXVL, LXVLL:
131 return op + " " + args[1] + "," + args[2] + "," + args[0]
132
133 case DCBT, DCBTST, DCBZ, DCBST, ICBI:
134 if args[0] == "0" || args[0] == "R0" {
135 return op + " (" + args[1] + ")"
136 }
137 return op + " (" + args[1] + ")(" + args[0] + ")"
138
139
140 case BCLR:
141 if int(inst.Args[0].(Imm))&20 == 20 {
142 return "RET"
143 }
144 return op + " " + strings.Join(args, ", ")
145 case BC:
146 bo := int(inst.Args[0].(Imm))
147 bi := int(inst.Args[1].(CondReg) - Cond0LT)
148 bcname := condName[((bo&0x8)>>1)|(bi&0x3)]
149 if bo&0x17 == 4 {
150 if bi >= 4 {
151 return fmt.Sprintf("B%s CR%d,%s", bcname, bi>>2, args[2])
152 } else {
153 return fmt.Sprintf("B%s %s", bcname, args[2])
154 }
155 }
156 return op + " " + strings.Join(args, ",")
157 case BCCTR:
158 if int(inst.Args[0].(Imm))&20 == 20 {
159 return "BR (CTR)"
160 }
161 return op + " " + strings.Join(args, ", ")
162 case BCCTRL:
163 if int(inst.Args[0].(Imm))&20 == 20 {
164 return "BL (CTR)"
165 }
166 return op + " " + strings.Join(args, ",")
167 case BCA, BCL, BCLA, BCLRL, BCTAR, BCTARL:
168 return op + " " + strings.Join(args, ",")
169 }
170 }
171
172
173
174
175
176 func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64) (string, uint64)) string {
177
178 if _, ok := arg.(Offset); ok {
179 if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
180 panic(fmt.Errorf("wrong table: offset not followed by register"))
181 }
182 }
183 switch arg := arg.(type) {
184 case Reg:
185 if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
186 return "0"
187 }
188 if arg == R30 {
189 return "g"
190 }
191 return strings.ToUpper(arg.String())
192 case CondReg:
193
194 if inst.Op == ISEL {
195 return fmt.Sprintf("$%d", (arg - Cond0LT))
196 }
197 bit := [4]string{"LT", "GT", "EQ", "SO"}[(arg-Cond0LT)%4]
198 if arg <= Cond0SO {
199 return bit
200 } else if arg > Cond0SO && arg <= Cond7SO {
201 return fmt.Sprintf("CR%d%s", int(arg-Cond0LT)/4, bit)
202 } else {
203 return fmt.Sprintf("CR%d", int(arg-CR0))
204 }
205 case Imm:
206 return fmt.Sprintf("$%d", arg)
207 case SpReg:
208 switch arg {
209 case 8:
210 return "LR"
211 case 9:
212 return "CTR"
213 }
214 return fmt.Sprintf("SPR(%d)", int(arg))
215 case PCRel:
216 addr := pc + uint64(int64(arg))
217 s, base := symname(addr)
218 if s != "" && addr == base {
219 return fmt.Sprintf("%s(SB)", s)
220 }
221 if inst.Op == BL && s != "" && (addr-base) == 8 {
222
223
224
225 return fmt.Sprintf("%s+%d(SB)", s, addr-base)
226 }
227 return fmt.Sprintf("%#x", addr)
228 case Label:
229 return fmt.Sprintf("%#x", int(arg))
230 case Offset:
231 reg := inst.Args[argIndex+1].(Reg)
232 removeArg(inst, argIndex+1)
233 if reg == R0 {
234 return fmt.Sprintf("%d(0)", int(arg))
235 }
236 return fmt.Sprintf("%d(R%d)", int(arg), reg-R0)
237 }
238 return fmt.Sprintf("???(%v)", arg)
239 }
240
241 func reverseMiddleOps(op Op) bool {
242 switch op {
243 case FMADD, FMADDCC, FMADDS, FMADDSCC, FMSUB, FMSUBCC, FMSUBS, FMSUBSCC, FNMADD, FNMADDCC, FNMADDS, FNMADDSCC, FNMSUB, FNMSUBCC, FNMSUBS, FNMSUBSCC, FSEL, FSELCC:
244 return true
245 }
246 return false
247 }
248
249 func reverseOperandOrder(op Op) bool {
250 switch op {
251
252 case ADD, ADDC, ADDE, ADDCC, ADDCCC:
253 return true
254 case MULLW, MULLWCC, MULHW, MULHWCC, MULLD, MULLDCC, MULHD, MULHDCC, MULLWO, MULLWOCC, MULHWU, MULHWUCC, MULLDO, MULLDOCC:
255 return true
256 case DIVD, DIVDCC, DIVDU, DIVDUCC, DIVDE, DIVDECC, DIVDEU, DIVDEUCC, DIVDO, DIVDOCC, DIVDUO, DIVDUOCC:
257 return true
258 case MODUD, MODSD, MODUW, MODSW:
259 return true
260 case FADD, FADDS, FSUB, FSUBS, FMUL, FMULS, FDIV, FDIVS, FMADD, FMADDS, FMSUB, FMSUBS, FNMADD, FNMADDS, FNMSUB, FNMSUBS, FMULSCC:
261 return true
262 case FADDCC, FADDSCC, FSUBCC, FMULCC, FDIVCC, FDIVSCC:
263 return true
264 case OR, ORCC, ORC, ORCCC, AND, ANDCC, ANDC, ANDCCC, XOR, XORCC, NAND, NANDCC, EQV, EQVCC, NOR, NORCC:
265 return true
266 case SLW, SLWCC, SLD, SLDCC, SRW, SRAW, SRWCC, SRAWCC, SRD, SRDCC, SRAD, SRADCC:
267 return true
268 }
269 return false
270 }
271
272
273 var revCondMap = map[string]string{
274 "LT": "GE", "GT": "LE", "EQ": "NE",
275 }
276
277
278
279
280 var condName = []string{
281 "GE",
282 "LE",
283 "NE",
284 "NSO",
285 "LT",
286 "GT",
287 "EQ",
288 "SO",
289 }
290
291
292 var plan9OpMap = map[Op]string{
293 LWARX: "LWAR",
294 LDARX: "LDAR",
295 LHARX: "LHAR",
296 LBARX: "LBAR",
297 LWAX: "MOVW",
298 LHAX: "MOVH",
299 LWAUX: "MOVWU",
300 LHAU: "MOVHU",
301 LHAUX: "MOVHU",
302 LDX: "MOVD",
303 LDUX: "MOVDU",
304 LWZX: "MOVWZ",
305 LWZUX: "MOVWZU",
306 LHZX: "MOVHZ",
307 LHZUX: "MOVHZU",
308 LBZX: "MOVBZ",
309 LBZUX: "MOVBZU",
310 LDBRX: "MOVDBR",
311 LWBRX: "MOVWBR",
312 LHBRX: "MOVHBR",
313 MCRF: "MOVFL",
314 XORI: "XOR",
315 ORI: "OR",
316 ANDICC: "ANDCC",
317 ANDC: "ANDN",
318 ANDCCC: "ANDNCC",
319 ADDEO: "ADDEV",
320 ADDEOCC: "ADDEVCC",
321 ADDO: "ADDV",
322 ADDOCC: "ADDVCC",
323 ADDMEO: "ADDMEV",
324 ADDMEOCC: "ADDMEVCC",
325 ADDCO: "ADDCV",
326 ADDCOCC: "ADDCVCC",
327 ADDZEO: "ADDZEV",
328 ADDZEOCC: "ADDZEVCC",
329 SUBFME: "SUBME",
330 SUBFMECC: "SUBMECC",
331 SUBFZE: "SUBZE",
332 SUBFZECC: "SUBZECC",
333 SUBFZEO: "SUBZEV",
334 SUBFZEOCC: "SUBZEVCC",
335 SUBF: "SUB",
336 SUBFC: "SUBC",
337 SUBFCC: "SUBCC",
338 SUBFCCC: "SUBCCC",
339 ORC: "ORN",
340 ORCCC: "ORNCC",
341 MULLWO: "MULLWV",
342 MULLWOCC: "MULLWVCC",
343 MULLDO: "MULLDV",
344 MULLDOCC: "MULLDVCC",
345 DIVDO: "DIVDV",
346 DIVDOCC: "DIVDVCC",
347 DIVDUO: "DIVDUV",
348 DIVDUOCC: "DIVDUVCC",
349 ADDI: "ADD",
350 MULLI: "MULLD",
351 SRADI: "SRAD",
352 STBCXCC: "STBCCC",
353 STWCXCC: "STWCCC",
354 STDCXCC: "STDCCC",
355 LI: "MOVD",
356 LBZ: "MOVBZ", STB: "MOVB",
357 LBZU: "MOVBZU", STBU: "MOVBU",
358 LHZ: "MOVHZ", LHA: "MOVH", STH: "MOVH",
359 LHZU: "MOVHZU", STHU: "MOVHU",
360 LWZ: "MOVWZ", LWA: "MOVW", STW: "MOVW",
361 LWZU: "MOVWZU", STWU: "MOVWU",
362 LD: "MOVD", STD: "MOVD",
363 LDU: "MOVDU", STDU: "MOVDU",
364 LFD: "FMOVD", STFD: "FMOVD",
365 LFS: "FMOVS", STFS: "FMOVS",
366 LFDX: "FMOVD", STFDX: "FMOVD",
367 LFDU: "FMOVDU", STFDU: "FMOVDU",
368 LFDUX: "FMOVDU", STFDUX: "FMOVDU",
369 LFSX: "FMOVS", STFSX: "FMOVS",
370 LFSU: "FMOVSU", STFSU: "FMOVSU",
371 LFSUX: "FMOVSU", STFSUX: "FMOVSU",
372 CMPD: "CMP", CMPDI: "CMP",
373 CMPW: "CMPW", CMPWI: "CMPW",
374 CMPLD: "CMPU", CMPLDI: "CMPU",
375 CMPLW: "CMPWU", CMPLWI: "CMPWU",
376 MTSPR: "MOVD", MFSPR: "MOVD",
377 B: "BR",
378 BL: "CALL",
379 }
380
View as plain text