Source file src/pkg/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go
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
34
35
36
37
38 if strings.IndexByte(s, ' ') > 0 {
39 t := strings.Split(s, " ")
40 args = append(args, t[0])
41 args = append(args, t[1])
42 } else {
43 args = append(args, s)
44 }
45 }
46 }
47 var op string
48 op = plan9OpMap[inst.Op]
49 if op == "" {
50 op = strings.ToUpper(inst.Op.String())
51 if op[len(op)-1] == '.' {
52 op = op[:len(op)-1] + "CC"
53 }
54 }
55
56 switch inst.Op {
57 default:
58 if len(args) == 0 {
59 return op
60 } else if len(args) == 1 {
61 return fmt.Sprintf("%s %s", op, args[0])
62 }
63 args = append(args, args[0])
64 return op + " " + strings.Join(args[1:], ",")
65 case SYNC:
66 if args[0] == "$1" {
67 return "LWSYNC"
68 }
69 return "HWSYNC"
70
71 case ISEL:
72 return "ISEL " + args[3] + "," + args[1] + "," + args[2] + "," + args[0]
73
74
75
76 case STB, STBU,
77 STH, STHU,
78 STW, STWU,
79 STD, STDU,
80 STQ:
81 return op + " " + strings.Join(args, ",")
82
83 case CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI:
84 if len(args) == 2 {
85 return op + " " + args[0] + "," + args[1]
86 } else if len(args) == 3 {
87 return op + " " + args[0] + "," + args[1] + "," + args[2]
88 }
89 return op + " " + args[0] + " ??"
90
91 case LIS:
92 return "ADDIS $0," + args[1] + "," + args[0]
93
94 case STBX, STBUX, STHX, STHUX, STWX, STWUX, STDX, STDUX,
95 STHBRX, STWBRX, STDBRX, STSWX, STFSX, STFSUX, STFDX, STFDUX, STFIWX, STFDPX:
96 return "MOV" + op[2:len(op)-1] + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
97
98 case STDCXCC, STWCXCC, STHCXCC, STBCXCC:
99 return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
100
101 case STXVD2X, STXVW4X:
102 return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
103
104
105 case LBZX, LBZUX, LHZX, LHZUX, LWZX, LWZUX, LDX, LDUX,
106 LHBRX, LWBRX, LDBRX, LSWX, LFSX, LFSUX, LFDX, LFDUX, LFIWAX, LFIWZX:
107 return "MOV" + op[1:len(op)-1] + " (" + args[2] + ")(" + args[1] + ")," + args[0]
108
109 case LDARX, LWARX, LHARX, LBARX:
110 return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
111
112 case LXVD2X, LXVW4X:
113 return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
114
115 case DCBT, DCBTST, DCBZ, DCBST:
116 return op + " (" + args[1] + ")"
117
118
119 case BCLR:
120 if int(inst.Args[0].(Imm))&20 == 20 {
121 return "RET"
122 }
123 return op + " " + strings.Join(args, ", ")
124 case BC:
125 if int(inst.Args[0].(Imm))&0x1c == 12 {
126 if len(args) == 4 {
127 return fmt.Sprintf("B%s %s,%s", args[1], args[2], args[3])
128 }
129 return fmt.Sprintf("B%s %s", args[1], args[2])
130 } else if int(inst.Args[0].(Imm))&0x1c == 4 && revCondMap[args[1]] != "" {
131 if len(args) == 4 {
132 return fmt.Sprintf("B%s %s,%s", revCondMap[args[1]], args[2], args[3])
133 }
134 return fmt.Sprintf("B%s %s", revCondMap[args[1]], args[2])
135 }
136 return op + " " + strings.Join(args, ",")
137 case BCCTR:
138 if int(inst.Args[0].(Imm))&20 == 20 {
139 return "BR (CTR)"
140 }
141 return op + " " + strings.Join(args, ", ")
142 case BCCTRL:
143 if int(inst.Args[0].(Imm))&20 == 20 {
144 return "BL (CTR)"
145 }
146 return op + " " + strings.Join(args, ",")
147 case BCA, BCL, BCLA, BCLRL, BCTAR, BCTARL:
148 return op + " " + strings.Join(args, ",")
149 }
150 }
151
152
153
154
155 func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64) (string, uint64)) string {
156
157 if _, ok := arg.(Offset); ok {
158 if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
159 panic(fmt.Errorf("wrong table: offset not followed by register"))
160 }
161 }
162 switch arg := arg.(type) {
163 case Reg:
164 if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
165 return "0"
166 }
167 if arg == R30 {
168 return "g"
169 }
170 return strings.ToUpper(arg.String())
171 case CondReg:
172
173 if inst.Op == ISEL {
174 return fmt.Sprintf("$%d", (arg - Cond0LT))
175 }
176 if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
177 return ""
178 } else if arg >= CR0 {
179 return fmt.Sprintf("CR%d", int(arg-CR0))
180 }
181 bit := [4]string{"LT", "GT", "EQ", "SO"}[(arg-Cond0LT)%4]
182 if arg <= Cond0SO {
183 return bit
184 }
185 return fmt.Sprintf("%s CR%d", bit, int(arg-Cond0LT)/4)
186 case Imm:
187 return fmt.Sprintf("$%d", arg)
188 case SpReg:
189 switch arg {
190 case 8:
191 return "LR"
192 case 9:
193 return "CTR"
194 }
195 return fmt.Sprintf("SPR(%d)", int(arg))
196 case PCRel:
197 addr := pc + uint64(int64(arg))
198 if s, base := symname(addr); s != "" && base == addr {
199 return fmt.Sprintf("%s(SB)", s)
200 }
201 return fmt.Sprintf("%#x", addr)
202 case Label:
203 return fmt.Sprintf("%#x", int(arg))
204 case Offset:
205 reg := inst.Args[argIndex+1].(Reg)
206 removeArg(inst, argIndex+1)
207 if reg == R0 {
208 return fmt.Sprintf("%d(0)", int(arg))
209 }
210 return fmt.Sprintf("%d(R%d)", int(arg), reg-R0)
211 }
212 return fmt.Sprintf("???(%v)", arg)
213 }
214
215
216 var revCondMap = map[string]string{
217 "LT": "GE", "GT": "LE", "EQ": "NE",
218 }
219
220
221 var plan9OpMap = map[Op]string{
222 LWARX: "LWAR",
223 LDARX: "LDAR",
224 LHARX: "LHAR",
225 LBARX: "LBAR",
226 ADDI: "ADD",
227 SRADI: "SRAD",
228 SUBF: "SUB",
229 LI: "MOVD",
230 LBZ: "MOVBZ", STB: "MOVB",
231 LBZU: "MOVBZU", STBU: "MOVBU",
232 LHZ: "MOVHZ", LHA: "MOVH", STH: "MOVH",
233 LHZU: "MOVHZU", STHU: "MOVHU",
234 LWZ: "MOVWZ", LWA: "MOVW", STW: "MOVW",
235 LWZU: "MOVWZU", STWU: "MOVWU",
236 LD: "MOVD", STD: "MOVD",
237 LDU: "MOVDU", STDU: "MOVDU",
238 CMPD: "CMP", CMPDI: "CMP",
239 CMPW: "CMPW", CMPWI: "CMPW",
240 CMPLD: "CMPU", CMPLDI: "CMPU",
241 CMPLW: "CMPWU", CMPLWI: "CMPWU",
242 MTSPR: "MOVD", MFSPR: "MOVD",
243 B: "BR",
244 BL: "CALL",
245 }
246
View as plain text