1 // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
3 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
4 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
5 // Portions Copyright © 1997-1999 Vita Nuova Limited
6 // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
7 // Portions Copyright © 2004,2006 Bruce Ellis
8 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
9 // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
10 // Portions Copyright © 2009 The Go Authors. All rights reserved.
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to deal
14 // in the Software without restriction, including without limitation the rights
15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 // copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
19 // The above copyright notice and this permission notice shall be included in
20 // all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 // Instruction layout.
62 {obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
63 {obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
64 {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
65 {obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
67 {AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
68 {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
69 {AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
70 {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
71 {AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
72 {AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
73 {AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
74 {AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
75 {AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
76 {AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
77 {AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
78 {AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
79 {AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
80 {AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
81 {AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
82 {AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
83 {AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
84 {AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
85 {AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
86 {AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
87 {AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
88 {AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
89 {AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
90 {AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
91 {AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
92 {AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
93 {AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
94 {AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
95 {AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
96 {AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
97 {AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
98 {AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
99 {AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
100 {AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
101 {AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
102 {AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
103 {AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
104 {ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
105 {ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
106 {ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
107 {ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
108 {AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
109 {AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
110 {AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
111 {AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
112 {AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
113 {AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
114 {AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
115 {AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
116 {ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
117 {ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
118 {ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
119 {ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
120 {ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
121 {ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
122 {ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
123 {ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
124 {ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
125 {ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
126 {ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
127 {ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
128 {ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
129 {ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
130 {ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
131 {ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
132 {ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
133 {ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
134 {ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
135 {ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
136 {ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
137 {ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
138 {ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
139 {ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
140 {ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
141 {ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
142 {ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
143 {AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
144 {AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
145 {AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
146 {AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
147 {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
148 {AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
149 {AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
150 {AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
152 /* store, short offset */
153 {AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
154 {AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
155 {AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
156 {AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
157 {AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
158 {AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
159 {AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
160 {AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
161 {AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
162 {AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
163 {AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
164 {AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
165 {AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
166 {AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
167 {AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
168 {AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
169 {AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
170 {AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
171 {AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
172 {AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
173 {AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
174 {AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
175 {AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
176 {AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
178 /* load, short offset */
179 {AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
180 {AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
181 {AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
182 {AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
183 {AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
184 {AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
185 {AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
186 {AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
187 {AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
188 {AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
189 {AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
190 {AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
191 {AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
192 {AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
193 {AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
194 {AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
195 {AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
196 {AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
197 {AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
198 {AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
199 {AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
200 {AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
201 {AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
202 {AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
204 /* store, long offset */
205 {AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
206 {AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
207 {AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
208 {AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
209 {AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
210 {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
211 {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
212 {AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
213 {AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
214 {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
215 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
216 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
217 {AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
218 {AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
219 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
220 {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
221 {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
222 {AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
223 {AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
224 {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
226 /* load, long offset */
227 {AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
228 {AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
229 {AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
230 {AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
231 {AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
232 {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
233 {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
234 {AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
235 {AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
236 {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
237 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
238 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
239 {AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
240 {AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
241 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
242 {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
243 {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
244 {AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
245 {AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
246 {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
248 {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 79, 4, 0},
249 {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 80, 8, 0},
251 {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 81, 8, 0},
254 {AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
255 {AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
256 {AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
257 {AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
258 {AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
259 {AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
260 {AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
261 {AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
262 {AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
263 {AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
264 {AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
265 {AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
266 {AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
267 {AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
268 {AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
270 /* load unsigned/long constants (TO DO: check) */
271 {AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
272 {AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
273 {AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
274 {AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
275 {AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
276 {AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
277 {AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
278 {AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
279 {AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
280 {AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
281 {ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
282 {ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
283 {ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
284 {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
285 {ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
286 {ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
287 {ABR, C_NONE, C_NONE, C_NONE, C_LBRAPIC, 11, 8, 0},
288 {ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
289 {ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
290 {ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
291 {ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
292 {ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
293 {ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
294 {ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
295 {ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
296 {ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
297 {ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
298 {ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
299 {AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
300 {AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
301 {AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
302 {AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
303 {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
304 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
305 {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
306 {AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
307 {AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
308 {AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
309 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
310 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
311 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
312 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
313 {ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
314 {AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
315 {ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
316 {ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
317 {AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
318 {AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
319 {AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
320 {ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
321 {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
322 {AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
323 {AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
324 {AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
325 {AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
326 {AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
327 {AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
328 {AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
329 {AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
330 {AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
331 {AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
332 {AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
333 {AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
334 {AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
335 {AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0}, /* mfmsr */
336 {AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsrd */
337 {AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
339 /* 64-bit special registers */
340 {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
341 {AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
342 {AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
343 {AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
344 {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
345 {AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
346 {AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
347 {AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
349 /* 32-bit special registers (gloss over sign-extension or not?) */
350 {AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
351 {AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
352 {AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
353 {AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
354 {AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
355 {AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
356 {AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
357 {AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
358 {AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
359 {AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
360 {AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
361 {AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
362 {AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
363 {AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
364 {AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
365 {AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
366 {AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
367 {AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
368 {ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
369 {ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
370 {ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
371 {ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
372 {ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
373 {ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
374 {ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
375 {ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
376 {AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
377 {AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
378 {ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
379 {ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
380 {ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
381 {ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
382 {AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
383 {AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
384 {AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
385 {AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
386 {AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
387 {ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
388 {ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
389 {ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
390 {ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
391 {ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
392 {ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
393 {ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
394 {ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
395 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
396 {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
397 {obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
398 {obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
399 {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
400 {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
401 {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
403 {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
406 var oprange [ALAST & obj.AMask][]Optab
408 var xcmp [C_NCLASS][C_NCLASS]bool
410 func span9(ctxt *obj.Link, cursym *obj.LSym) {
412 if p == nil || p.Link == nil { // handle external functions and ELF section symbols
416 ctxt.Autosize = int32(p.To.Offset)
418 if oprange[AANDN&obj.AMask] == nil {
427 for p = p.Link; p != nil; p = p.Link {
433 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
434 ctxt.Diag("zero-width instruction\n%v", p)
445 * if any procedure is large enough to
446 * generate a large SBRA branch, then
447 * generate extra passes putting branches
448 * around jmps to fix. this is rare.
455 if ctxt.Debugvlog != 0 {
456 fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
460 for p = cursym.Text.Link; p != nil; p = p.Link {
464 // very large conditional branches
465 if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
466 otxt = p.Pcond.Pc - c
467 if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
472 q.To.Type = obj.TYPE_BRANCH
479 q.To.Type = obj.TYPE_BRANCH
480 q.Pcond = q.Link.Link
490 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
491 ctxt.Diag("zero-width instruction\n%v", p)
502 c += -c & (FuncAlign - 1)
506 * lay out the code, emitting code and data relocations.
509 cursym.Grow(cursym.Size)
514 for p := cursym.Text.Link; p != nil; p = p.Link {
518 if int(o.size) > 4*len(out) {
519 log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
521 asmout(ctxt, p, o, out[:])
522 for i = 0; i < int32(o.size/4); i++ {
523 ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
529 func isint32(v int64) bool {
530 return int64(int32(v)) == v
533 func isuint32(v uint64) bool {
534 return uint64(uint32(v)) == v
537 func aclass(ctxt *obj.Link, a *obj.Addr) int {
543 if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
546 if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
549 if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR {
552 if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 {
567 if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 {
570 if a.Reg == REG_FPSCR {
573 if a.Reg == REG_MSR {
580 case obj.NAME_EXTERN,
585 ctxt.Instoffset = a.Offset
586 if a.Sym != nil { // use relocation
587 if a.Sym.Type == obj.STLSBSS {
588 if ctxt.Flag_shared {
598 case obj.NAME_GOTREF:
602 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
603 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
609 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
610 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
616 ctxt.Instoffset = a.Offset
617 if ctxt.Instoffset == 0 {
620 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
628 case obj.TYPE_TEXTSIZE:
635 ctxt.Instoffset = a.Offset
637 if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
640 if isint32(ctxt.Instoffset) {
648 case obj.NAME_EXTERN,
654 if s.Type == obj.SCONST {
655 ctxt.Instoffset = a.Offset
659 ctxt.Instoffset = a.Offset
661 /* not sure why this barfs */
665 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
666 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
672 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
673 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
682 if ctxt.Instoffset >= 0 {
683 if ctxt.Instoffset == 0 {
686 if ctxt.Instoffset <= 0x7fff {
689 if ctxt.Instoffset <= 0xffff {
692 if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
695 if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
701 if ctxt.Instoffset >= -0x8000 {
704 if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
707 if isint32(ctxt.Instoffset) {
712 case obj.TYPE_BRANCH:
713 if a.Sym != nil && ctxt.Flag_dynlink {
722 func prasm(p *obj.Prog) {
723 fmt.Printf("%v\n", p)
726 func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
731 a1 = int(p.From.Class)
733 a1 = aclass(ctxt, &p.From) + 1
734 p.From.Class = int8(a1)
740 a3 = int(p.From3.Class)
742 a3 = aclass(ctxt, p.From3) + 1
743 p.From3.Class = int8(a3)
748 a4 := int(p.To.Class)
750 a4 = aclass(ctxt, &p.To) + 1
751 p.To.Class = int8(a4)
760 //print("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4);
761 ops := oprange[p.As&obj.AMask]
767 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && c4[op.a4] {
768 p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
773 ctxt.Diag("illegal combination %v %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
781 func cmp(a int, b int) bool {
787 if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
792 if b == C_ZCON || b == C_SCON {
797 if b == C_ZCON || b == C_SCON {
802 if b == C_LR || b == C_XER || b == C_CTR {
838 return r0iszero != 0 /*TypeKind(100016)*/
842 if b == C_ZOREG || b == C_SOREG {
860 func (x ocmp) Len() int {
864 func (x ocmp) Swap(i, j int) {
865 x[i], x[j] = x[j], x[i]
868 func (x ocmp) Less(i, j int) bool {
871 n := int(p1.as) - int(p2.as)
875 n = int(p1.a1) - int(p2.a1)
879 n = int(p1.a2) - int(p2.a2)
883 n = int(p1.a3) - int(p2.a3)
887 n = int(p1.a4) - int(p2.a4)
893 func opset(a, b0 obj.As) {
894 oprange[a&obj.AMask] = oprange[b0]
897 func buildop(ctxt *obj.Link) {
900 for i := 0; i < C_NCLASS; i++ {
901 for n = 0; n < C_NCLASS; n++ {
907 for n = 0; optab[n].as != obj.AXXX; n++ {
909 sort.Sort(ocmp(optab[:n]))
910 for i := 0; i < n; i++ {
914 for optab[i].as == r {
917 oprange[r0] = optab[start:i]
922 ctxt.Diag("unknown op in build: %v", obj.Aconv(r))
923 log.Fatalf("bad code")
925 case ADCBF: /* unary indexed: op (b+a); op (b) */
934 case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
939 case AREM: /* macro */
962 case ADIVW: /* op Rb[,Ra],Rd */
1001 opset(AMULLDVCC, r0)
1009 opset(ADIVDUVCC, r0)
1012 case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
1017 case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
1026 case AAND: /* logical op Rb,Rs,Ra; no literal */
1041 case AADDME: /* op Ra, Rd */
1045 opset(AADDMEVCC, r0)
1049 opset(AADDZEVCC, r0)
1053 opset(ASUBMEVCC, r0)
1057 opset(ASUBZEVCC, r0)
1077 case AEXTSB: /* op Rs, Ra */
1083 opset(ACNTLZWCC, r0)
1087 opset(ACNTLZDCC, r0)
1089 case AFABS: /* fop [s,]d */
1101 opset(AFCTIWZCC, r0)
1105 opset(AFCTIDZCC, r0)
1111 opset(AFRSQRTECC, r0)
1115 opset(AFSQRTSCC, r0)
1133 opset(AFMADDSCC, r0)
1137 opset(AFMSUBSCC, r0)
1139 opset(AFNMADDCC, r0)
1141 opset(AFNMADDSCC, r0)
1143 opset(AFNMSUBCC, r0)
1145 opset(AFNMSUBSCC, r0)
1158 opset(AMTFSB0CC, r0)
1160 opset(AMTFSB1CC, r0)
1162 case ANEG: /* op [Ra,] Rd */
1168 case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
1181 case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
1184 case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
1187 case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
1232 case ASYSCALL: /* just the op; flow of control */
1262 AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
1265 /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
1266 AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals */
1267 AMOVD, /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
1268 AMOVB, /* macro: move byte with sign extension */
1269 AMOVBU, /* macro: move byte with sign extension & update */
1272 /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
1273 ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */
1291 func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
1292 return o<<26 | xo<<1 | oe<<10 | rc&1
1295 func OPCC(o uint32, xo uint32, rc uint32) uint32 {
1296 return OPVCC(o, xo, 0, rc)
1299 func OP(o uint32, xo uint32) uint32 {
1300 return OPVCC(o, xo, 0, 0)
1303 /* the order is dest, a/s, b/imm for both arithmetic and logical operations */
1304 func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 {
1305 return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11
1308 func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
1309 return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
1312 func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
1313 return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
1316 func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
1317 return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
1320 func OP_BR(op uint32, li uint32, aa uint32) uint32 {
1321 return op | li&0x03FFFFFC | aa<<1
1324 func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 {
1325 return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1
1328 func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
1329 return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
1332 func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 {
1333 return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1
1337 /* each rhs is OPVCC(_, _, _, _) */
1338 OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0
1339 OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0
1340 OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0
1341 OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0
1342 OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0
1343 OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0
1344 OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0
1345 OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0
1346 OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0
1347 OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0
1348 OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0
1349 OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0
1350 OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0
1351 OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0
1352 OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0
1353 OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0
1354 OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0
1355 OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0
1356 OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0
1357 OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0
1358 OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0
1359 OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0
1360 OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0
1361 OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0
1362 OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0
1363 OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0
1364 OP_OR = 31<<26 | 444<<1 | 0<<10 | 0
1365 OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0
1366 OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0
1367 OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0
1368 OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0
1369 OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0
1370 OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0
1371 OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0
1374 func oclass(a *obj.Addr) int {
1375 return int(a.Class) - 1
1383 // opform returns the form (D_FORM or DS_FORM) of an instruction. Used to decide on
1384 // which relocation to use with a load or store and only supports the needed
1386 func opform(ctxt *obj.Link, insn uint32) int {
1389 ctxt.Diag("bad insn in loadform: %x", insn)
1390 case OPVCC(58, 0, 0, 0), // ld
1391 OPVCC(58, 0, 0, 0) | 1<<1, // lwa
1392 OPVCC(62, 0, 0, 0): // std
1394 case OP_ADDI, // add
1395 OPVCC(32, 0, 0, 0), // lwz
1396 OPVCC(42, 0, 0, 0), // lha
1397 OPVCC(40, 0, 0, 0), // lhz
1398 OPVCC(34, 0, 0, 0), // lbz
1399 OPVCC(50, 0, 0, 0), // lfd
1400 OPVCC(48, 0, 0, 0), // lfs
1401 OPVCC(36, 0, 0, 0), // stw
1402 OPVCC(44, 0, 0, 0), // sth
1403 OPVCC(38, 0, 0, 0), // stb
1404 OPVCC(54, 0, 0, 0), // stfd
1405 OPVCC(52, 0, 0, 0): // stfs
1411 // Encode instructions and create relocation for accessing s+d according to the
1412 // instruction op with source or destination (as appropriate) register reg.
1413 func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op uint32) (o1, o2 uint32) {
1415 form := opform(ctxt, op)
1416 if ctxt.Flag_shared {
1421 o1 = AOP_IRR(OP_ADDIS, REGTMP, base, 0)
1422 o2 = AOP_IRR(op, uint32(reg), REGTMP, 0)
1423 rel := obj.Addrel(ctxt.Cursym)
1424 rel.Off = int32(ctxt.Pc)
1428 if ctxt.Flag_shared {
1431 rel.Type = obj.R_ADDRPOWER_TOCREL
1433 rel.Type = obj.R_ADDRPOWER_TOCREL_DS
1439 rel.Type = obj.R_ADDRPOWER
1441 rel.Type = obj.R_ADDRPOWER_DS
1450 func getmask(m []byte, v uint32) bool {
1453 if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
1464 for i := 0; i < 32; i++ {
1465 if v&(1<<uint(31-i)) != 0 {
1470 if i >= 32 || v&(1<<uint(31-i)) == 0 {
1476 if v&(1<<uint(31-i)) != 0 {
1487 func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
1489 ctxt.Diag("cannot generate mask #%x\n%v", v, p)
1494 * 64-bit masks (rldic etc)
1496 func getmask64(m []byte, v uint64) bool {
1499 for i := 0; i < 64; i++ {
1500 if v&(uint64(1)<<uint(63-i)) != 0 {
1505 if i >= 64 || v&(uint64(1)<<uint(63-i)) == 0 {
1511 if v&(uint64(1)<<uint(63-i)) != 0 {
1522 func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
1523 if !getmask64(m, v) {
1524 ctxt.Diag("cannot generate mask #%x\n%v", v, p)
1528 func loadu32(r int, d int64) uint32 {
1530 if isuint32(uint64(d)) {
1531 return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v))
1533 return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v))
1536 func high16adjusted(d int32) uint16 {
1538 return uint16((d >> 16) + 1)
1540 return uint16(d >> 16)
1543 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
1550 //print("%v => case %d\n", p, o->type);
1553 ctxt.Diag("unknown type %d", o.type_)
1556 case 0: /* pseudo ops */
1559 case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
1560 if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
1561 v := regoff(ctxt, &p.From)
1562 if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
1564 ctxt.Diag("literal operation on R0\n%v", p)
1567 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
1571 o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg))
1573 case 2: /* int/cr/fp op Rb,[Ra],Rd */
1579 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
1581 case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
1582 d := vregoff(ctxt, &p.From)
1585 r := int(p.From.Reg)
1589 if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) {
1590 ctxt.Diag("literal operation on R0\n%v", p)
1595 log.Fatalf("invalid handling of %v", p)
1598 if r == REGZERO && isuint32(uint64(d)) {
1599 o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
1605 if int64(int16(d)) != d {
1606 log.Fatalf("invalid handling of %v", p)
1610 o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
1612 case 4: /* add/mul $scon,[r1],r2 */
1613 v := regoff(ctxt, &p.From)
1619 if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 {
1620 ctxt.Diag("literal operation on R0\n%v", p)
1622 if int32(int16(v)) != v {
1623 log.Fatalf("mishandled instruction %v", p)
1625 o1 = AOP_IRR(opirr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(v))
1627 case 5: /* syscall */
1628 o1 = oprrr(ctxt, p.As)
1630 case 6: /* logical op Rb,[Rs,]Ra; no literal */
1636 o1 = LOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
1638 case 7: /* mov r, soreg ==> stw o(r) */
1644 v := regoff(ctxt, &p.To)
1645 if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 {
1647 ctxt.Diag("illegal indexed instruction\n%v", p)
1649 if ctxt.Flag_shared && r == REG_R13 {
1650 rel := obj.Addrel(ctxt.Cursym)
1651 rel.Off = int32(ctxt.Pc)
1653 // This (and the matching part in the load case
1654 // below) are the only places in the ppc64 toolchain
1655 // that knows the name of the tls variable. Possibly
1656 // we could add some assembly syntax so that the name
1657 // of the variable does not have to be assumed.
1658 rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
1659 rel.Type = obj.R_POWER_TLS
1661 o1 = AOP_RRR(opstorex(ctxt, p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
1663 if int32(int16(v)) != v {
1664 log.Fatalf("mishandled instruction %v", p)
1666 o1 = AOP_IRR(opstore(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(v))
1669 case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
1670 r := int(p.From.Reg)
1675 v := regoff(ctxt, &p.From)
1676 if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
1678 ctxt.Diag("illegal indexed instruction\n%v", p)
1680 if ctxt.Flag_shared && r == REG_R13 {
1681 rel := obj.Addrel(ctxt.Cursym)
1682 rel.Off = int32(ctxt.Pc)
1684 rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
1685 rel.Type = obj.R_POWER_TLS
1687 o1 = AOP_RRR(oploadx(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
1689 if int32(int16(v)) != v {
1690 log.Fatalf("mishandled instruction %v", p)
1692 o1 = AOP_IRR(opload(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(v))
1695 case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
1696 r := int(p.From.Reg)
1701 v := regoff(ctxt, &p.From)
1702 if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
1704 ctxt.Diag("illegal indexed instruction\n%v", p)
1706 o1 = AOP_RRR(oploadx(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
1708 o1 = AOP_IRR(opload(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(v))
1710 o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
1712 case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
1718 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r))
1720 case 11: /* br/bl lbra */
1724 v = int32(p.Pcond.Pc - p.Pc)
1726 ctxt.Diag("odd branch target address\n%v", p)
1730 if v < -(1<<25) || v >= 1<<24 {
1731 ctxt.Diag("branch too far\n%v", p)
1735 o1 = OP_BR(opirr(ctxt, p.As), uint32(v), 0)
1736 if p.To.Sym != nil {
1737 rel := obj.Addrel(ctxt.Cursym)
1738 rel.Off = int32(ctxt.Pc)
1741 v += int32(p.To.Offset)
1743 ctxt.Diag("odd branch target address\n%v", p)
1748 rel.Type = obj.R_CALLPOWER
1750 o2 = 0x60000000 // nop, sometimes overwritten by ld r2, 24(r1) when dynamic linking
1752 case 12: /* movb r,r (extsb); movw r,r (extsw) */
1753 if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
1754 v := regoff(ctxt, &p.From)
1755 if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
1756 ctxt.Diag("literal operation on R0\n%v", p)
1759 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
1764 o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0)
1766 o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0)
1769 case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
1771 o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31)
1772 } else if p.As == AMOVH {
1773 o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0)
1774 } else if p.As == AMOVHZ {
1775 o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31)
1776 } else if p.As == AMOVWZ {
1777 o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */
1779 ctxt.Diag("internal: bad mov[bhw]z\n%v", p)
1782 case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
1788 d := vregoff(ctxt, p.From3)
1790 maskgen64(ctxt, p, mask[:], uint64(d))
1793 case ARLDCL, ARLDCLCC:
1794 a = int(mask[0]) /* MB */
1796 ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
1799 case ARLDCR, ARLDCRCC:
1800 a = int(mask[1]) /* ME */
1802 ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
1806 ctxt.Diag("unexpected op in rldc case\n%v", p)
1810 o1 = LOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
1811 o1 |= (uint32(a) & 31) << 6
1813 o1 |= 1 << 5 /* mb[5] is top bit */
1816 case 17, /* bc bo,bi,lbra (same for now) */
1817 16: /* bc bo,bi,sbra */
1820 if p.From.Type == obj.TYPE_CONST {
1821 a = int(regoff(ctxt, &p.From))
1829 v = int32(p.Pcond.Pc - p.Pc)
1832 ctxt.Diag("odd branch target address\n%v", p)
1836 if v < -(1<<16) || v >= 1<<15 {
1837 ctxt.Diag("branch too far\n%v", p)
1839 o1 = OP_BC(opirr(ctxt, p.As), uint32(a), uint32(r), uint32(v), 0)
1841 case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
1843 if p.As == ABC || p.As == ABCL {
1844 v = regoff(ctxt, &p.To) & 31
1846 v = 20 /* unconditional */
1848 o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (REG_LR&0x1f)<<16 | ((REG_LR>>5)&0x1f)<<11
1849 o2 = OPVCC(19, 16, 0, 0)
1850 if p.As == ABL || p.As == ABCL {
1853 o2 = OP_BCR(o2, uint32(v), uint32(p.To.Index))
1855 case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
1857 if p.As == ABC || p.As == ABCL {
1858 v = regoff(ctxt, &p.From) & 31
1860 v = 20 /* unconditional */
1866 switch oclass(&p.To) {
1868 o1 = OPVCC(19, 528, 0, 0)
1871 o1 = OPVCC(19, 16, 0, 0)
1874 ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p)
1878 if p.As == ABL || p.As == ABCL {
1881 o1 = OP_BCR(o1, uint32(v), uint32(r))
1883 case 19: /* mov $lcon,r ==> cau+or */
1884 d := vregoff(ctxt, &p.From)
1886 if p.From.Sym == nil {
1887 o1 = loadu32(int(p.To.Reg), d)
1888 o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
1890 o1, o2 = symbolAccess(ctxt, p.From.Sym, d, p.To.Reg, OP_ADDI)
1893 //if(dlm) reloc(&p->from, p->pc, 0);
1895 case 20: /* add $ucon,,r */
1896 v := regoff(ctxt, &p.From)
1902 if p.As == AADD && (r0iszero == 0 /*TypeKind(100016)*/ && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
1903 ctxt.Diag("literal operation on R0\n%v", p)
1905 o1 = AOP_IRR(opirr(ctxt, -p.As), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
1907 case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
1908 if p.To.Reg == REGTMP || p.Reg == REGTMP {
1909 ctxt.Diag("can't synthesize large constant\n%v", p)
1911 d := vregoff(ctxt, &p.From)
1912 o1 = loadu32(REGTMP, d)
1913 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
1918 o3 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), REGTMP, uint32(r))
1919 if p.From.Sym != nil {
1920 ctxt.Diag("%v is not supported", p)
1923 //if(dlm) reloc(&p->from, p->pc, 0);
1925 case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
1926 if p.To.Reg == REGTMP || p.Reg == REGTMP {
1927 ctxt.Diag("can't synthesize large constant\n%v", p)
1929 d := vregoff(ctxt, &p.From)
1930 o1 = loadu32(REGTMP, d)
1931 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
1936 o3 = LOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), REGTMP, uint32(r))
1937 if p.From.Sym != nil {
1938 ctxt.Diag("%v is not supported", p)
1941 //if(dlm) reloc(&p->from, p->pc, 0);
1945 /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
1946 v := regoff(ctxt, &p.From)
1969 ctxt.Diag("unexpected op in sldi case\n%v", p)
1974 o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F))
1975 o1 |= (uint32(a) & 31) << 6
1980 o1 |= 1 << 5 /* mb[5] is top bit */
1982 if p.As == ASLDCC || p.As == ASRDCC {
1986 case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
1987 if p.To.Reg == REGTMP {
1988 ctxt.Diag("can't synthesize large constant\n%v", p)
1990 v := regoff(ctxt, &p.From)
1991 r := int(p.From.Reg)
1995 o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
1996 o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
1998 case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
1999 v := regoff(ctxt, p.From3)
2001 r := int(p.From.Reg)
2002 o1 = AOP_IRR(opirr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(v))
2004 case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
2005 if p.To.Reg == REGTMP || p.From.Reg == REGTMP {
2006 ctxt.Diag("can't synthesize large constant\n%v", p)
2008 v := regoff(ctxt, p.From3)
2009 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
2010 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
2011 o3 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
2012 if p.From.Sym != nil {
2013 ctxt.Diag("%v is not supported", p)
2016 //if(dlm) reloc(&p->from3, p->pc, 0);
2018 case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
2019 v := regoff(ctxt, &p.From)
2021 d := vregoff(ctxt, p.From3)
2023 maskgen64(ctxt, p, mask[:], uint64(d))
2026 case ARLDC, ARLDCCC:
2027 a = int(mask[0]) /* MB */
2028 if int32(mask[1]) != (63 - v) {
2029 ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
2032 case ARLDCL, ARLDCLCC:
2033 a = int(mask[0]) /* MB */
2035 ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
2038 case ARLDCR, ARLDCRCC:
2039 a = int(mask[1]) /* ME */
2041 ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
2045 ctxt.Diag("unexpected op in rldic case\n%v", p)
2049 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
2050 o1 |= (uint32(a) & 31) << 6
2055 o1 |= 1 << 5 /* mb[5] is top bit */
2058 case 30: /* rldimi $sh,s,$mask,a */
2059 v := regoff(ctxt, &p.From)
2061 d := vregoff(ctxt, p.From3)
2063 maskgen64(ctxt, p, mask[:], uint64(d))
2064 if int32(mask[1]) != (63 - v) {
2065 ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
2067 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
2068 o1 |= (uint32(mask[0]) & 31) << 6
2072 if mask[0]&0x20 != 0 {
2073 o1 |= 1 << 5 /* mb[5] is top bit */
2076 case 31: /* dword */
2077 d := vregoff(ctxt, &p.From)
2079 if ctxt.Arch.ByteOrder == binary.BigEndian {
2080 o1 = uint32(d >> 32)
2084 o2 = uint32(d >> 32)
2087 if p.From.Sym != nil {
2088 rel := obj.Addrel(ctxt.Cursym)
2089 rel.Off = int32(ctxt.Pc)
2091 rel.Sym = p.From.Sym
2092 rel.Add = p.From.Offset
2093 rel.Type = obj.R_ADDR
2098 case 32: /* fmul frc,fra,frd */
2104 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6
2106 case 33: /* fabs [frb,]frd; fmr. frb,frd */
2107 r := int(p.From.Reg)
2109 if oclass(&p.From) == C_NONE {
2112 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), 0, uint32(r))
2114 case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
2115 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
2117 case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
2118 v := regoff(ctxt, &p.To)
2124 o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
2125 o2 = AOP_IRR(opstore(ctxt, p.As), uint32(p.From.Reg), REGTMP, uint32(v))
2127 case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
2128 v := regoff(ctxt, &p.From)
2130 r := int(p.From.Reg)
2134 o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
2135 o2 = AOP_IRR(opload(ctxt, p.As), uint32(p.To.Reg), REGTMP, uint32(v))
2137 case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
2138 v := regoff(ctxt, &p.From)
2140 r := int(p.From.Reg)
2144 o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
2145 o2 = AOP_IRR(opload(ctxt, p.As), uint32(p.To.Reg), REGTMP, uint32(v))
2146 o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
2149 o1 = uint32(regoff(ctxt, &p.From))
2151 case 41: /* stswi */
2152 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11
2155 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11
2157 case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
2158 o1 = AOP_RRR(oprrr(ctxt, p.As), 0, uint32(p.From.Index), uint32(p.From.Reg))
2160 case 44: /* indexed store */
2161 o1 = AOP_RRR(opstorex(ctxt, p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(p.To.Reg))
2163 case 45: /* indexed load */
2164 o1 = AOP_RRR(oploadx(ctxt, p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg))
2166 case 46: /* plain op */
2167 o1 = oprrr(ctxt, p.As)
2169 case 47: /* op Ra, Rd; also op [Ra,] Rd */
2170 r := int(p.From.Reg)
2175 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), 0)
2177 case 48: /* op Rs, Ra */
2178 r := int(p.From.Reg)
2183 o1 = LOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), uint32(r), 0)
2185 case 49: /* op Rb; op $n, Rb */
2186 if p.From.Type != obj.TYPE_REG { /* tlbie $L, rB */
2187 v := regoff(ctxt, &p.From) & 1
2188 o1 = AOP_RRR(oprrr(ctxt, p.As), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21
2190 o1 = AOP_RRR(oprrr(ctxt, p.As), 0, 0, uint32(p.From.Reg))
2193 case 50: /* rem[u] r1[,r2],r3 */
2199 v := oprrr(ctxt, p.As)
2200 t := v & (1<<10 | 1) /* OE|Rc */
2201 o1 = AOP_RRR(v&^t, REGTMP, uint32(r), uint32(p.From.Reg))
2202 o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg))
2203 o3 = AOP_RRR(OP_SUBF|t, uint32(p.To.Reg), REGTMP, uint32(r))
2207 /* Clear top 32 bits */
2208 o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5
2211 case 51: /* remd[u] r1[,r2],r3 */
2217 v := oprrr(ctxt, p.As)
2218 t := v & (1<<10 | 1) /* OE|Rc */
2219 o1 = AOP_RRR(v&^t, REGTMP, uint32(r), uint32(p.From.Reg))
2220 o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg))
2221 o3 = AOP_RRR(OP_SUBF|t, uint32(p.To.Reg), REGTMP, uint32(r))
2223 case 52: /* mtfsbNx cr(n) */
2224 v := regoff(ctxt, &p.From) & 31
2226 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(v), 0, 0)
2228 case 53: /* mffsX ,fr1 */
2229 o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0)
2231 case 54: /* mov msr,r1; mov r1, msr*/
2232 if oclass(&p.From) == C_REG {
2234 o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0)
2236 o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0)
2239 o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0)
2242 case 55: /* op Rb, Rd */
2243 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.To.Reg), 0, uint32(p.From.Reg))
2245 case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
2246 v := regoff(ctxt, &p.From)
2252 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(r), uint32(p.To.Reg), uint32(v)&31)
2253 if (p.As == ASRAD || p.As == ASRADCC) && (v&0x20 != 0) {
2254 o1 |= 1 << 1 /* mb[5] */
2257 case 57: /* slw $sh,[s,]a -> rlwinm ... */
2258 v := regoff(ctxt, &p.From)
2266 * Let user (gs) shoot himself in the foot.
2267 * qc has already complained.
2270 ctxt->diag("illegal shift %ld\n%v", v, p);
2278 if p.As == ASRW || p.As == ASRWCC { /* shift right */
2284 mask[1] = uint8(31 - v)
2287 o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1]))
2288 if p.As == ASLWCC || p.As == ASRWCC {
2292 case 58: /* logical $andcon,[s],a */
2293 v := regoff(ctxt, &p.From)
2299 o1 = LOP_IRR(opirr(ctxt, p.As), uint32(p.To.Reg), uint32(r), uint32(v))
2301 case 59: /* or/and $ucon,,r */
2302 v := regoff(ctxt, &p.From)
2308 o1 = LOP_IRR(opirr(ctxt, -p.As), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */
2310 case 60: /* tw to,a,b */
2311 r := int(regoff(ctxt, &p.From) & 31)
2313 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
2315 case 61: /* tw to,a,$simm */
2316 r := int(regoff(ctxt, &p.From) & 31)
2318 v := regoff(ctxt, &p.To)
2319 o1 = AOP_IRR(opirr(ctxt, p.As), uint32(r), uint32(p.Reg), uint32(v))
2321 case 62: /* rlwmi $sh,s,$mask,a */
2322 v := regoff(ctxt, &p.From)
2325 maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3)))
2326 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
2327 o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
2329 case 63: /* rlwmi b,s,$mask,a */
2331 maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3)))
2333 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
2334 o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
2336 case 64: /* mtfsf fr[, $m] {,fpcsr} */
2338 if p.From3Type() != obj.TYPE_NONE {
2339 v = regoff(ctxt, p.From3) & 255
2343 o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11
2345 case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
2347 ctxt.Diag("must specify FPSCR(n)\n%v", p)
2349 o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12
2351 case 66: /* mov spr,r1; mov r1,spr, also dcr */
2354 if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 {
2357 if REG_DCR0 <= v && v <= REG_DCR0+1023 {
2358 o1 = OPVCC(31, 451, 0, 0) /* mtdcr */
2360 o1 = OPVCC(31, 467, 0, 0) /* mtspr */
2364 v = int32(p.From.Reg)
2365 if REG_DCR0 <= v && v <= REG_DCR0+1023 {
2366 o1 = OPVCC(31, 323, 0, 0) /* mfdcr */
2368 o1 = OPVCC(31, 339, 0, 0) /* mfspr */
2372 o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11
2374 case 67: /* mcrf crfD,crfS */
2375 if p.From.Type != obj.TYPE_REG || p.From.Reg < REG_CR0 || REG_CR7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
2376 ctxt.Diag("illegal CR field number\n%v", p)
2378 o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
2380 case 68: /* mfcr rD; mfocrf CRM,rD */
2381 if p.From.Type == obj.TYPE_REG && REG_CR0 <= p.From.Reg && p.From.Reg <= REG_CR7 {
2382 v := int32(1 << uint(7-(p.To.Reg&7))) /* CR(n) */
2383 o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */
2385 o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */
2388 case 69: /* mtcrf CRM,rS */
2390 if p.From3Type() != obj.TYPE_NONE {
2392 ctxt.Diag("can't use both mask and CR(n)\n%v", p)
2394 v = regoff(ctxt, p.From3) & 0xff
2399 v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
2403 o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12
2405 case 70: /* [f]cmp r,r,cr*/
2410 r = (int(p.Reg) & 7) << 2
2412 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
2414 case 71: /* cmp[l] r,i,cr*/
2419 r = (int(p.Reg) & 7) << 2
2421 o1 = AOP_RRR(opirr(ctxt, p.As), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff
2423 case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
2424 o1 = AOP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), 0, uint32(p.To.Reg))
2426 case 73: /* mcrfs crfD,crfS */
2427 if p.From.Type != obj.TYPE_REG || p.From.Reg != REG_FPSCR || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
2428 ctxt.Diag("illegal FPSCR/CR field number\n%v", p)
2430 o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0)
2432 case 77: /* syscall $scon, syscall Rx */
2433 if p.From.Type == obj.TYPE_CONST {
2434 if p.From.Offset > BIG || p.From.Offset < -BIG {
2435 ctxt.Diag("illegal syscall, sysnum too large: %v", p)
2437 o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset))
2438 } else if p.From.Type == obj.TYPE_REG {
2439 o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg))
2441 ctxt.Diag("illegal syscall: %v", p)
2442 o1 = 0x7fe00008 // trap always
2445 o2 = oprrr(ctxt, p.As)
2446 o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO) // XOR R0, R0
2448 case 78: /* undef */
2449 o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
2450 always to be an illegal instruction." */
2452 /* relocation operations */
2454 v := vregoff(ctxt, &p.To)
2455 o1, o2 = symbolAccess(ctxt, p.To.Sym, v, p.From.Reg, opstore(ctxt, p.As))
2457 //if(dlm) reloc(&p->to, p->pc, 1);
2460 v := vregoff(ctxt, &p.From)
2461 o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, p.As))
2463 //if(dlm) reloc(&p->from, p->pc, 1);
2466 v := vregoff(ctxt, &p.From)
2467 o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, p.As))
2468 o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
2470 //if(dlm) reloc(&p->from, p->pc, 1);
2473 if p.From.Offset != 0 {
2474 ctxt.Diag("invalid offset against tls var %v", p)
2476 o1 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGZERO, 0)
2477 rel := obj.Addrel(ctxt.Cursym)
2478 rel.Off = int32(ctxt.Pc)
2480 rel.Sym = p.From.Sym
2481 rel.Type = obj.R_POWER_TLS_LE
2484 if p.From.Offset != 0 {
2485 ctxt.Diag("invalid offset against tls var %v", p)
2487 o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
2488 o2 = AOP_IRR(opload(ctxt, AMOVD), uint32(p.To.Reg), uint32(p.To.Reg), 0)
2489 rel := obj.Addrel(ctxt.Cursym)
2490 rel.Off = int32(ctxt.Pc)
2492 rel.Sym = p.From.Sym
2493 rel.Type = obj.R_POWER_TLS_IE
2496 v := vregoff(ctxt, &p.To)
2498 ctxt.Diag("invalid offset against GOT slot %v", p)
2501 o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
2502 o2 = AOP_IRR(opload(ctxt, AMOVD), uint32(p.To.Reg), uint32(p.To.Reg), 0)
2503 rel := obj.Addrel(ctxt.Cursym)
2504 rel.Off = int32(ctxt.Pc)
2506 rel.Sym = p.From.Sym
2507 rel.Type = obj.R_ADDRPOWER_GOT
2518 func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
2523 return ctxt.Instoffset
2526 func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
2527 return int32(vregoff(ctxt, a))
2530 func oprrr(ctxt *obj.Link, a obj.As) uint32 {
2533 return OPVCC(31, 266, 0, 0)
2535 return OPVCC(31, 266, 0, 1)
2537 return OPVCC(31, 266, 1, 0)
2539 return OPVCC(31, 266, 1, 1)
2541 return OPVCC(31, 10, 0, 0)
2543 return OPVCC(31, 10, 0, 1)
2545 return OPVCC(31, 10, 1, 0)
2547 return OPVCC(31, 10, 1, 1)
2549 return OPVCC(31, 138, 0, 0)
2551 return OPVCC(31, 138, 0, 1)
2553 return OPVCC(31, 138, 1, 0)
2555 return OPVCC(31, 138, 1, 1)
2557 return OPVCC(31, 234, 0, 0)
2559 return OPVCC(31, 234, 0, 1)
2561 return OPVCC(31, 234, 1, 0)
2563 return OPVCC(31, 234, 1, 1)
2565 return OPVCC(31, 202, 0, 0)
2567 return OPVCC(31, 202, 0, 1)
2569 return OPVCC(31, 202, 1, 0)
2571 return OPVCC(31, 202, 1, 1)
2574 return OPVCC(31, 28, 0, 0)
2576 return OPVCC(31, 28, 0, 1)
2578 return OPVCC(31, 60, 0, 0)
2580 return OPVCC(31, 60, 0, 1)
2583 return OPVCC(31, 0, 0, 0) | 1<<21 /* L=1 */
2585 return OPVCC(31, 32, 0, 0) | 1<<21
2587 return OPVCC(31, 0, 0, 0) /* L=0 */
2589 return OPVCC(31, 32, 0, 0)
2592 return OPVCC(31, 26, 0, 0)
2594 return OPVCC(31, 26, 0, 1)
2596 return OPVCC(31, 58, 0, 0)
2598 return OPVCC(31, 58, 0, 1)
2601 return OPVCC(19, 257, 0, 0)
2603 return OPVCC(19, 129, 0, 0)
2605 return OPVCC(19, 289, 0, 0)
2607 return OPVCC(19, 225, 0, 0)
2609 return OPVCC(19, 33, 0, 0)
2611 return OPVCC(19, 449, 0, 0)
2613 return OPVCC(19, 417, 0, 0)
2615 return OPVCC(19, 193, 0, 0)
2618 return OPVCC(31, 86, 0, 0)
2620 return OPVCC(31, 470, 0, 0)
2622 return OPVCC(31, 54, 0, 0)
2624 return OPVCC(31, 278, 0, 0)
2626 return OPVCC(31, 246, 0, 0)
2628 return OPVCC(31, 1014, 0, 0)
2631 return OPVCC(31, 491, 0, 0)
2633 case AREMCC, ADIVWCC:
2634 return OPVCC(31, 491, 0, 1)
2637 return OPVCC(31, 491, 1, 0)
2639 case AREMVCC, ADIVWVCC:
2640 return OPVCC(31, 491, 1, 1)
2643 return OPVCC(31, 459, 0, 0)
2645 case AREMUCC, ADIVWUCC:
2646 return OPVCC(31, 459, 0, 1)
2648 case AREMUV, ADIVWUV:
2649 return OPVCC(31, 459, 1, 0)
2651 case AREMUVCC, ADIVWUVCC:
2652 return OPVCC(31, 459, 1, 1)
2655 return OPVCC(31, 489, 0, 0)
2657 case AREMDCC, ADIVDCC:
2658 return OPVCC(31, 489, 0, 1)
2660 case AREMDV, ADIVDV:
2661 return OPVCC(31, 489, 1, 0)
2663 case AREMDVCC, ADIVDVCC:
2664 return OPVCC(31, 489, 1, 1)
2666 case AREMDU, ADIVDU:
2667 return OPVCC(31, 457, 0, 0)
2669 case AREMDUCC, ADIVDUCC:
2670 return OPVCC(31, 457, 0, 1)
2672 case AREMDUV, ADIVDUV:
2673 return OPVCC(31, 457, 1, 0)
2675 case AREMDUVCC, ADIVDUVCC:
2676 return OPVCC(31, 457, 1, 1)
2679 return OPVCC(31, 854, 0, 0)
2682 return OPVCC(31, 284, 0, 0)
2684 return OPVCC(31, 284, 0, 1)
2687 return OPVCC(31, 954, 0, 0)
2689 return OPVCC(31, 954, 0, 1)
2691 return OPVCC(31, 922, 0, 0)
2693 return OPVCC(31, 922, 0, 1)
2695 return OPVCC(31, 986, 0, 0)
2697 return OPVCC(31, 986, 0, 1)
2700 return OPVCC(63, 264, 0, 0)
2702 return OPVCC(63, 264, 0, 1)
2704 return OPVCC(63, 21, 0, 0)
2706 return OPVCC(63, 21, 0, 1)
2708 return OPVCC(59, 21, 0, 0)
2710 return OPVCC(59, 21, 0, 1)
2712 return OPVCC(63, 32, 0, 0)
2714 return OPVCC(63, 0, 0, 0)
2716 return OPVCC(63, 846, 0, 0)
2718 return OPVCC(63, 846, 0, 1)
2720 return OPVCC(63, 14, 0, 0)
2722 return OPVCC(63, 14, 0, 1)
2724 return OPVCC(63, 15, 0, 0)
2726 return OPVCC(63, 15, 0, 1)
2728 return OPVCC(63, 814, 0, 0)
2730 return OPVCC(63, 814, 0, 1)
2732 return OPVCC(63, 815, 0, 0)
2734 return OPVCC(63, 815, 0, 1)
2736 return OPVCC(63, 18, 0, 0)
2738 return OPVCC(63, 18, 0, 1)
2740 return OPVCC(59, 18, 0, 0)
2742 return OPVCC(59, 18, 0, 1)
2744 return OPVCC(63, 29, 0, 0)
2746 return OPVCC(63, 29, 0, 1)
2748 return OPVCC(59, 29, 0, 0)
2750 return OPVCC(59, 29, 0, 1)
2752 case AFMOVS, AFMOVD:
2753 return OPVCC(63, 72, 0, 0) /* load */
2755 return OPVCC(63, 72, 0, 1)
2757 return OPVCC(63, 28, 0, 0)
2759 return OPVCC(63, 28, 0, 1)
2761 return OPVCC(59, 28, 0, 0)
2763 return OPVCC(59, 28, 0, 1)
2765 return OPVCC(63, 25, 0, 0)
2767 return OPVCC(63, 25, 0, 1)
2769 return OPVCC(59, 25, 0, 0)
2771 return OPVCC(59, 25, 0, 1)
2773 return OPVCC(63, 136, 0, 0)
2775 return OPVCC(63, 136, 0, 1)
2777 return OPVCC(63, 40, 0, 0)
2779 return OPVCC(63, 40, 0, 1)
2781 return OPVCC(63, 31, 0, 0)
2783 return OPVCC(63, 31, 0, 1)
2785 return OPVCC(59, 31, 0, 0)
2787 return OPVCC(59, 31, 0, 1)
2789 return OPVCC(63, 30, 0, 0)
2791 return OPVCC(63, 30, 0, 1)
2793 return OPVCC(59, 30, 0, 0)
2795 return OPVCC(59, 30, 0, 1)
2797 return OPVCC(59, 24, 0, 0)
2799 return OPVCC(59, 24, 0, 1)
2801 return OPVCC(63, 12, 0, 0)
2803 return OPVCC(63, 12, 0, 1)
2805 return OPVCC(63, 26, 0, 0)
2807 return OPVCC(63, 26, 0, 1)
2809 return OPVCC(63, 23, 0, 0)
2811 return OPVCC(63, 23, 0, 1)
2813 return OPVCC(63, 22, 0, 0)
2815 return OPVCC(63, 22, 0, 1)
2817 return OPVCC(59, 22, 0, 0)
2819 return OPVCC(59, 22, 0, 1)
2821 return OPVCC(63, 20, 0, 0)
2823 return OPVCC(63, 20, 0, 1)
2825 return OPVCC(59, 20, 0, 0)
2827 return OPVCC(59, 20, 0, 1)
2830 return OPVCC(31, 982, 0, 0)
2832 return OPVCC(19, 150, 0, 0)
2835 return OPVCC(63, 70, 0, 0)
2837 return OPVCC(63, 70, 0, 1)
2839 return OPVCC(63, 38, 0, 0)
2841 return OPVCC(63, 38, 0, 1)
2844 return OPVCC(31, 75, 0, 0)
2846 return OPVCC(31, 75, 0, 1)
2848 return OPVCC(31, 11, 0, 0)
2850 return OPVCC(31, 11, 0, 1)
2852 return OPVCC(31, 235, 0, 0)
2854 return OPVCC(31, 235, 0, 1)
2856 return OPVCC(31, 235, 1, 0)
2858 return OPVCC(31, 235, 1, 1)
2861 return OPVCC(31, 73, 0, 0)
2863 return OPVCC(31, 73, 0, 1)
2865 return OPVCC(31, 9, 0, 0)
2867 return OPVCC(31, 9, 0, 1)
2869 return OPVCC(31, 233, 0, 0)
2871 return OPVCC(31, 233, 0, 1)
2873 return OPVCC(31, 233, 1, 0)
2875 return OPVCC(31, 233, 1, 1)
2878 return OPVCC(31, 476, 0, 0)
2880 return OPVCC(31, 476, 0, 1)
2882 return OPVCC(31, 104, 0, 0)
2884 return OPVCC(31, 104, 0, 1)
2886 return OPVCC(31, 104, 1, 0)
2888 return OPVCC(31, 104, 1, 1)
2890 return OPVCC(31, 124, 0, 0)
2892 return OPVCC(31, 124, 0, 1)
2894 return OPVCC(31, 444, 0, 0)
2896 return OPVCC(31, 444, 0, 1)
2898 return OPVCC(31, 412, 0, 0)
2900 return OPVCC(31, 412, 0, 1)
2903 return OPVCC(19, 50, 0, 0)
2905 return OPVCC(19, 51, 0, 0)
2907 return OPVCC(19, 18, 0, 0)
2909 return OPVCC(19, 274, 0, 0)
2912 return OPVCC(20, 0, 0, 0)
2914 return OPVCC(20, 0, 0, 1)
2916 return OPVCC(23, 0, 0, 0)
2918 return OPVCC(23, 0, 0, 1)
2921 return OPVCC(30, 8, 0, 0)
2923 return OPVCC(30, 9, 0, 0)
2926 return OPVCC(17, 1, 0, 0)
2929 return OPVCC(31, 24, 0, 0)
2931 return OPVCC(31, 24, 0, 1)
2933 return OPVCC(31, 27, 0, 0)
2935 return OPVCC(31, 27, 0, 1)
2938 return OPVCC(31, 792, 0, 0)
2940 return OPVCC(31, 792, 0, 1)
2942 return OPVCC(31, 794, 0, 0)
2944 return OPVCC(31, 794, 0, 1)
2947 return OPVCC(31, 536, 0, 0)
2949 return OPVCC(31, 536, 0, 1)
2951 return OPVCC(31, 539, 0, 0)
2953 return OPVCC(31, 539, 0, 1)
2956 return OPVCC(31, 40, 0, 0)
2958 return OPVCC(31, 40, 0, 1)
2960 return OPVCC(31, 40, 1, 0)
2962 return OPVCC(31, 40, 1, 1)
2964 return OPVCC(31, 8, 0, 0)
2966 return OPVCC(31, 8, 0, 1)
2968 return OPVCC(31, 8, 1, 0)
2970 return OPVCC(31, 8, 1, 1)
2972 return OPVCC(31, 136, 0, 0)
2974 return OPVCC(31, 136, 0, 1)
2976 return OPVCC(31, 136, 1, 0)
2978 return OPVCC(31, 136, 1, 1)
2980 return OPVCC(31, 232, 0, 0)
2982 return OPVCC(31, 232, 0, 1)
2984 return OPVCC(31, 232, 1, 0)
2986 return OPVCC(31, 232, 1, 1)
2988 return OPVCC(31, 200, 0, 0)
2990 return OPVCC(31, 200, 0, 1)
2992 return OPVCC(31, 200, 1, 0)
2994 return OPVCC(31, 200, 1, 1)
2997 return OPVCC(31, 598, 0, 0)
2999 return OPVCC(31, 598, 0, 0) | 2<<21
3002 return OPVCC(31, 306, 0, 0)
3004 return OPVCC(31, 274, 0, 0)
3006 return OPVCC(31, 566, 0, 0)
3008 return OPVCC(31, 498, 0, 0)
3010 return OPVCC(31, 434, 0, 0)
3012 return OPVCC(31, 915, 0, 0)
3014 return OPVCC(31, 851, 0, 0)
3016 return OPVCC(31, 402, 0, 0)
3019 return OPVCC(31, 4, 0, 0)
3021 return OPVCC(31, 68, 0, 0)
3024 return OPVCC(31, 316, 0, 0)
3026 return OPVCC(31, 316, 0, 1)
3029 ctxt.Diag("bad r/r opcode %v", obj.Aconv(a))
3033 func opirr(ctxt *obj.Link, a obj.As) uint32 {
3036 return OPVCC(14, 0, 0, 0)
3038 return OPVCC(12, 0, 0, 0)
3040 return OPVCC(13, 0, 0, 0)
3042 return OPVCC(15, 0, 0, 0) /* ADDIS/CAU */
3045 return OPVCC(28, 0, 0, 0)
3047 return OPVCC(29, 0, 0, 0) /* ANDIS./ANDIU. */
3050 return OPVCC(18, 0, 0, 0)
3052 return OPVCC(18, 0, 0, 0) | 1
3054 return OPVCC(18, 0, 0, 0) | 1
3056 return OPVCC(18, 0, 0, 0) | 1
3058 return OPVCC(16, 0, 0, 0)
3060 return OPVCC(16, 0, 0, 0) | 1
3063 return AOP_RRR(16<<26, 12, 2, 0)
3065 return AOP_RRR(16<<26, 4, 0, 0)
3067 return AOP_RRR(16<<26, 12, 1, 0)
3069 return AOP_RRR(16<<26, 4, 1, 0)
3071 return AOP_RRR(16<<26, 12, 0, 0)
3073 return AOP_RRR(16<<26, 4, 2, 0)
3075 return AOP_RRR(16<<26, 4, 3, 0)
3077 return AOP_RRR(16<<26, 12, 3, 0)
3080 return OPVCC(11, 0, 0, 0) | 1<<21 /* L=1 */
3082 return OPVCC(10, 0, 0, 0) | 1<<21
3084 return OPVCC(11, 0, 0, 0) /* L=0 */
3086 return OPVCC(10, 0, 0, 0)
3088 return OPVCC(31, 597, 0, 0)
3091 return OPVCC(7, 0, 0, 0)
3094 return OPVCC(24, 0, 0, 0)
3096 return OPVCC(25, 0, 0, 0) /* ORIS/ORIU */
3099 return OPVCC(20, 0, 0, 0) /* rlwimi */
3101 return OPVCC(20, 0, 0, 1)
3103 return OPVCC(30, 0, 0, 0) | 3<<2 /* rldimi */
3105 return OPVCC(30, 0, 0, 1) | 3<<2
3108 return OPVCC(21, 0, 0, 0) /* rlwinm */
3110 return OPVCC(21, 0, 0, 1)
3113 return OPVCC(30, 0, 0, 0) /* rldicl */
3115 return OPVCC(30, 0, 0, 1)
3117 return OPVCC(30, 1, 0, 0) /* rldicr */
3119 return OPVCC(30, 1, 0, 1)
3121 return OPVCC(30, 0, 0, 0) | 2<<2
3123 return OPVCC(30, 0, 0, 1) | 2<<2
3126 return OPVCC(31, 824, 0, 0)
3128 return OPVCC(31, 824, 0, 1)
3130 return OPVCC(31, (413 << 1), 0, 0)
3132 return OPVCC(31, (413 << 1), 0, 1)
3135 return OPVCC(31, 725, 0, 0)
3138 return OPVCC(8, 0, 0, 0)
3141 return OPVCC(3, 0, 0, 0)
3143 return OPVCC(2, 0, 0, 0)
3146 return OPVCC(26, 0, 0, 0) /* XORIL */
3148 return OPVCC(27, 0, 0, 0) /* XORIU */
3151 ctxt.Diag("bad opcode i/r %v", obj.Aconv(a))
3158 func opload(ctxt *obj.Link, a obj.As) uint32 {
3161 return OPVCC(58, 0, 0, 0) /* ld */
3163 return OPVCC(58, 0, 0, 1) /* ldu */
3165 return OPVCC(32, 0, 0, 0) /* lwz */
3167 return OPVCC(33, 0, 0, 0) /* lwzu */
3169 return OPVCC(58, 0, 0, 0) | 1<<1 /* lwa */
3173 return OPVCC(34, 0, 0, 0)
3176 case AMOVBU, AMOVBZU:
3177 return OPVCC(35, 0, 0, 0)
3179 return OPVCC(50, 0, 0, 0)
3181 return OPVCC(51, 0, 0, 0)
3183 return OPVCC(48, 0, 0, 0)
3185 return OPVCC(49, 0, 0, 0)
3187 return OPVCC(42, 0, 0, 0)
3189 return OPVCC(43, 0, 0, 0)
3191 return OPVCC(40, 0, 0, 0)
3193 return OPVCC(41, 0, 0, 0)
3195 return OPVCC(46, 0, 0, 0) /* lmw */
3198 ctxt.Diag("bad load opcode %v", obj.Aconv(a))
3203 * indexed load a(b),d
3205 func oploadx(ctxt *obj.Link, a obj.As) uint32 {
3208 return OPVCC(31, 23, 0, 0) /* lwzx */
3210 return OPVCC(31, 55, 0, 0) /* lwzux */
3212 return OPVCC(31, 341, 0, 0) /* lwax */
3214 return OPVCC(31, 373, 0, 0) /* lwaux */
3217 return OPVCC(31, 87, 0, 0) /* lbzx */
3219 case AMOVBU, AMOVBZU:
3220 return OPVCC(31, 119, 0, 0) /* lbzux */
3222 return OPVCC(31, 599, 0, 0) /* lfdx */
3224 return OPVCC(31, 631, 0, 0) /* lfdux */
3226 return OPVCC(31, 535, 0, 0) /* lfsx */
3228 return OPVCC(31, 567, 0, 0) /* lfsux */
3230 return OPVCC(31, 343, 0, 0) /* lhax */
3232 return OPVCC(31, 375, 0, 0) /* lhaux */
3234 return OPVCC(31, 790, 0, 0) /* lhbrx */
3236 return OPVCC(31, 534, 0, 0) /* lwbrx */
3238 return OPVCC(31, 279, 0, 0) /* lhzx */
3240 return OPVCC(31, 311, 0, 0) /* lhzux */
3242 return OPVCC(31, 310, 0, 0) /* eciwx */
3244 return OPVCC(31, 20, 0, 0) /* lwarx */
3246 return OPVCC(31, 84, 0, 0)
3248 return OPVCC(31, 533, 0, 0) /* lswx */
3250 return OPVCC(31, 21, 0, 0) /* ldx */
3252 return OPVCC(31, 53, 0, 0) /* ldux */
3255 ctxt.Diag("bad loadx opcode %v", obj.Aconv(a))
3262 func opstore(ctxt *obj.Link, a obj.As) uint32 {
3265 return OPVCC(38, 0, 0, 0) /* stb */
3267 case AMOVBU, AMOVBZU:
3268 return OPVCC(39, 0, 0, 0) /* stbu */
3270 return OPVCC(54, 0, 0, 0) /* stfd */
3272 return OPVCC(55, 0, 0, 0) /* stfdu */
3274 return OPVCC(52, 0, 0, 0) /* stfs */
3276 return OPVCC(53, 0, 0, 0) /* stfsu */
3279 return OPVCC(44, 0, 0, 0) /* sth */
3281 case AMOVHZU, AMOVHU:
3282 return OPVCC(45, 0, 0, 0) /* sthu */
3284 return OPVCC(47, 0, 0, 0) /* stmw */
3286 return OPVCC(31, 725, 0, 0) /* stswi */
3289 return OPVCC(36, 0, 0, 0) /* stw */
3291 case AMOVWZU, AMOVWU:
3292 return OPVCC(37, 0, 0, 0) /* stwu */
3294 return OPVCC(62, 0, 0, 0) /* std */
3296 return OPVCC(62, 0, 0, 1) /* stdu */
3299 ctxt.Diag("unknown store opcode %v", obj.Aconv(a))
3304 * indexed store s,a(b)
3306 func opstorex(ctxt *obj.Link, a obj.As) uint32 {
3309 return OPVCC(31, 215, 0, 0) /* stbx */
3311 case AMOVBU, AMOVBZU:
3312 return OPVCC(31, 247, 0, 0) /* stbux */
3314 return OPVCC(31, 727, 0, 0) /* stfdx */
3316 return OPVCC(31, 759, 0, 0) /* stfdux */
3318 return OPVCC(31, 663, 0, 0) /* stfsx */
3320 return OPVCC(31, 695, 0, 0) /* stfsux */
3323 return OPVCC(31, 407, 0, 0) /* sthx */
3325 return OPVCC(31, 918, 0, 0) /* sthbrx */
3327 case AMOVHZU, AMOVHU:
3328 return OPVCC(31, 439, 0, 0) /* sthux */
3331 return OPVCC(31, 151, 0, 0) /* stwx */
3333 case AMOVWZU, AMOVWU:
3334 return OPVCC(31, 183, 0, 0) /* stwux */
3336 return OPVCC(31, 661, 0, 0) /* stswx */
3338 return OPVCC(31, 662, 0, 0) /* stwbrx */
3340 return OPVCC(31, 150, 0, 1) /* stwcx. */
3342 return OPVCC(31, 214, 0, 1) /* stwdx. */
3344 return OPVCC(31, 438, 0, 0) /* ecowx */
3346 return OPVCC(31, 149, 0, 0) /* stdx */
3348 return OPVCC(31, 181, 0, 0) /* stdux */
3351 ctxt.Diag("unknown storex opcode %v", obj.Aconv(a))