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