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
39 // Instruction layout.
60 {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
61 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0},
63 {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0},
64 {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0},
65 {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0},
66 {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0},
67 {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0},
69 {ASUB, C_REG, C_REG, C_REG, 2, 4, 0},
70 {AADD, C_REG, C_REG, C_REG, 2, 4, 0},
71 {AAND, C_REG, C_REG, C_REG, 2, 4, 0},
72 {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0},
73 {AADD, C_REG, C_NONE, C_REG, 2, 4, 0},
74 {AAND, C_REG, C_NONE, C_REG, 2, 4, 0},
76 {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
77 {ASLL, C_REG, C_REG, C_REG, 9, 4, 0},
79 {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0},
80 {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0},
81 {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0},
82 {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
83 {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
84 {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0},
86 {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
87 {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
88 {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
89 {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
90 {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
91 {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
92 {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
93 {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
94 {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
95 {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
96 {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
97 {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
98 {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
99 {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
100 {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
101 {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
102 {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
103 {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
105 {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
106 {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
107 {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
108 {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
109 {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
110 {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
111 {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
112 {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
113 {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
114 {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
115 {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
116 {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
117 {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
118 {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
119 {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
120 {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
121 {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
122 {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
124 {AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
125 {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
126 {AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
127 {AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
128 {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
129 {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
130 {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
131 {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
132 {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
133 {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
134 {AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
135 {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
136 {AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
137 {AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
138 {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
139 {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0},
140 {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
141 {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
142 {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
143 {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
144 {AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0},
145 {AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0},
146 {AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0},
147 {AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0},
148 {AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0},
150 {AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
151 {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
152 {AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
153 {AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
154 {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
155 {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
156 {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
157 {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
158 {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
159 {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
160 {AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
161 {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
162 {AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
163 {AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
164 {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
165 {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0},
166 {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
167 {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
168 {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
169 {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
170 {AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0},
171 {AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0},
172 {AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0},
173 {AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0},
174 {AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0},
176 {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
177 {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
178 {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
179 {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
180 {AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB},
181 {AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB},
182 {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
183 {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
184 {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
185 {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
186 {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
187 {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
188 {AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0},
189 {AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0},
191 {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
192 {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
193 {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0},
194 {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0},
196 {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0},
197 {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0},
198 {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0},
199 {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0},
200 {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0},
201 {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0},
202 {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0},
203 {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0},
205 {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0},
207 {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0},
208 {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0},
209 {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0},
210 {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0},
212 {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0},
213 {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0},
214 {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0},
215 {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0},
217 {AADD, C_UCON, C_REG, C_REG, 25, 8, 0},
218 {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0},
219 {AAND, C_UCON, C_REG, C_REG, 25, 8, 0},
220 {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0},
222 {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0},
223 {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0},
224 {AADD, C_LCON, C_REG, C_REG, 23, 12, 0},
225 {AAND, C_LCON, C_REG, C_REG, 23, 12, 0},
227 {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0},
228 {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0},
230 {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0},
232 {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0},
233 {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
234 {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
235 {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0},
237 {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
238 {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
240 {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO},
241 {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK},
243 {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
244 {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
245 {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
246 {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
247 {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
248 {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
249 {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
250 {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
251 {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
253 {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB},
254 {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB},
255 {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB},
256 {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
257 {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
258 {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
259 {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO},
260 {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO},
261 {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO},
262 {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
263 {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
265 {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
266 {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
267 {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
268 {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
269 {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
270 {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
271 {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
272 {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
273 {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
275 {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB},
276 {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB},
277 {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB},
278 {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
279 {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
280 {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
281 {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO},
282 {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO},
283 {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO},
284 {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
285 {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
287 {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0},
288 {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0},
289 {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0},
290 {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0},
292 {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0},
293 {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0},
295 {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0},
296 {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0},
297 {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0},
298 {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0},
300 {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0},
302 {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0},
303 {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0},
304 {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0},
305 {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0},
307 {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */
308 {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
309 {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
310 {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0},
312 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0},
313 {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0},
314 {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0},
315 {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0},
316 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0},
317 {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
318 {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
320 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0},
323 var oprange [ALAST & obj.AMask][]Optab
325 var xcmp [C_NCLASS][C_NCLASS]bool
327 func span0(ctxt *obj.Link, cursym *obj.LSym) {
329 if p == nil || p.Link == nil { // handle external functions and ELF section symbols
333 ctxt.Autosize = int32(p.To.Offset + 8)
335 if oprange[AOR&obj.AMask] == nil {
344 for p = p.Link; p != nil; p = p.Link {
350 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
351 ctxt.Diag("zero-width instruction\n%v", p)
362 * if any procedure is large enough to
363 * generate a large SBRA branch, then
364 * generate extra passes putting branches
365 * around jmps to fix. this is rare.
372 if ctxt.Debugvlog != 0 {
373 fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
377 for p = cursym.Text.Link; p != nil; p = p.Link {
381 // very large conditional branches
382 if o.type_ == 6 && p.Pcond != nil {
383 otxt = p.Pcond.Pc - c
384 if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
390 q.To.Type = obj.TYPE_BRANCH
398 q.To.Type = obj.TYPE_BRANCH
399 q.Pcond = q.Link.Link
409 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
410 ctxt.Diag("zero-width instruction\n%v", p)
421 c += -c & (FuncAlign - 1)
425 * lay out the code, emitting code and data relocations.
428 cursym.Grow(cursym.Size)
433 for p := cursym.Text.Link; p != nil; p = p.Link {
437 if int(o.size) > 4*len(out) {
438 log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
440 asmout(ctxt, p, o, out[:])
441 for i = 0; i < int32(o.size/4); i++ {
442 ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
448 func isint32(v int64) bool {
449 return int64(int32(v)) == v
452 func isuint32(v uint64) bool {
453 return uint64(uint32(v)) == v
456 func aclass(ctxt *obj.Link, a *obj.Addr) int {
462 if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
465 if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
468 if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
471 if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
484 case obj.NAME_EXTERN,
489 ctxt.Instoffset = a.Offset
490 if a.Sym != nil { // use relocation
491 if a.Sym.Type == obj.STLSBSS {
499 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
500 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
506 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
507 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
513 ctxt.Instoffset = a.Offset
514 if ctxt.Instoffset == 0 {
517 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
525 case obj.TYPE_TEXTSIZE:
532 ctxt.Instoffset = a.Offset
534 if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
537 if isint32(ctxt.Instoffset) {
545 case obj.NAME_EXTERN,
551 if s.Type == obj.SCONST {
552 ctxt.Instoffset = a.Offset
556 ctxt.Instoffset = a.Offset
557 if s.Type == obj.STLSBSS {
558 return C_STCON // address of TLS variable
563 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
564 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
570 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
571 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
580 if ctxt.Instoffset >= 0 {
581 if ctxt.Instoffset == 0 {
584 if ctxt.Instoffset <= 0x7fff {
587 if ctxt.Instoffset <= 0xffff {
590 if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
593 if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
596 return C_LCON // C_DCON
599 if ctxt.Instoffset >= -0x8000 {
602 if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
605 if isint32(ctxt.Instoffset) {
608 return C_LCON // C_DCON
610 case obj.TYPE_BRANCH:
617 func prasm(p *obj.Prog) {
618 fmt.Printf("%v\n", p)
621 func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
622 if oprange[AOR&obj.AMask] == nil {
630 a1 = int(p.From.Class)
632 a1 = aclass(ctxt, &p.From) + 1
633 p.From.Class = int8(a1)
637 a3 := int(p.To.Class)
639 a3 = aclass(ctxt, &p.To) + 1
640 p.To.Class = int8(a3)
649 //print("oplook %P %d %d %d\n", p, a1, a2, a3);
651 ops := oprange[p.As&obj.AMask]
656 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
657 p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
662 ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3))
670 func cmp(a int, b int) bool {
676 if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
687 if b == C_ZCON || b == C_SCON {
698 if b == C_ZCON || b == C_SCON {
734 return r0iszero != 0 /*TypeKind(100016)*/
738 if b == C_ZOREG || b == C_SOREG {
753 func (x ocmp) Len() int {
757 func (x ocmp) Swap(i, j int) {
758 x[i], x[j] = x[j], x[i]
761 func (x ocmp) Less(i, j int) bool {
764 n := int(p1.as) - int(p2.as)
768 n = int(p1.a1) - int(p2.a1)
772 n = int(p1.a2) - int(p2.a2)
776 n = int(p1.a3) - int(p2.a3)
783 func opset(a, b0 obj.As) {
784 oprange[a&obj.AMask] = oprange[b0]
787 func buildop(ctxt *obj.Link) {
790 for i := 0; i < C_NCLASS; i++ {
791 for n = 0; n < C_NCLASS; n++ {
797 for n = 0; optab[n].as != obj.AXXX; n++ {
799 sort.Sort(ocmp(optab[:n]))
800 for i := 0; i < n; i++ {
804 for optab[i].as == r {
807 oprange[r0] = optab[start:i]
812 ctxt.Diag("unknown op in build: %v", obj.Aconv(r))
813 log.Fatalf("bad code")
940 func OP(x uint32, y uint32) uint32 {
944 func SP(x uint32, y uint32) uint32 {
948 func BCOND(x uint32, y uint32) uint32 {
952 func MMU(x uint32, y uint32) uint32 {
953 return SP(2, 0) | 16<<21 | x<<3 | y<<0
956 func FPF(x uint32, y uint32) uint32 {
957 return SP(2, 1) | 16<<21 | x<<3 | y<<0
960 func FPD(x uint32, y uint32) uint32 {
961 return SP(2, 1) | 17<<21 | x<<3 | y<<0
964 func FPW(x uint32, y uint32) uint32 {
965 return SP(2, 1) | 20<<21 | x<<3 | y<<0
968 func FPV(x uint32, y uint32) uint32 {
969 return SP(2, 1) | 21<<21 | x<<3 | y<<0
972 func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
973 return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
976 func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
977 return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
980 func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
981 return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
984 func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
985 return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
988 func OP_JMP(op uint32, i uint32) uint32 {
989 return op | i&0x3FFFFFF
992 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
1000 ctxt.Diag("unknown type %d %v", o.type_)
1003 case 0: /* pseudo ops */
1006 case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
1009 a = AADDU // sign-extended to high 32 bits
1011 o1 = OP_RRR(oprrr(ctxt, a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
1013 case 2: /* add/sub r1,[r2],r3 */
1019 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1021 case 3: /* mov $soreg, r ==> or/add $i,o,r */
1022 v := regoff(ctxt, &p.From)
1024 r := int(p.From.Reg)
1029 if o.a1 == C_ANDCON {
1033 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
1035 case 4: /* add $scon,[r1],r2 */
1036 v := regoff(ctxt, &p.From)
1043 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1045 case 5: /* syscall */
1046 o1 = oprrr(ctxt, p.As)
1048 case 6: /* beq r1,[r2],sbra */
1053 v = int32(p.Pcond.Pc-p.Pc-4) >> 2
1055 if (v<<16)>>16 != v {
1056 ctxt.Diag("short branch too far\n%v", p)
1058 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
1059 // for ABFPT and ABFPF only: always fill delay slot with 0
1060 // see comments in func preprocess for details.
1063 case 7: /* mov r, soreg ==> sw o(r) */
1068 v := regoff(ctxt, &p.To)
1069 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1071 case 8: /* mov soreg, r ==> lw o(r) */
1072 r := int(p.From.Reg)
1076 v := regoff(ctxt, &p.From)
1077 o1 = OP_IRR(opirr(ctxt, -p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1079 case 9: /* sll r1,[r2],r3 */
1085 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
1087 case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
1088 v := regoff(ctxt, &p.From)
1093 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
1098 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1100 case 11: /* jmp lbra */
1102 if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
1103 // use PC-relative branch for short branches
1108 v = int32(p.Pcond.Pc-p.Pc-4) >> 2
1110 if (v<<16)>>16 == v {
1111 o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
1116 v = int32(p.Pc) >> 2
1118 v = int32(p.Pcond.Pc) >> 2
1120 o1 = OP_JMP(opirr(ctxt, p.As), uint32(v))
1121 if p.To.Sym == nil {
1122 p.To.Sym = ctxt.Cursym.Text.From.Sym
1123 p.To.Offset = p.Pcond.Pc
1125 rel := obj.Addrel(ctxt.Cursym)
1126 rel.Off = int32(ctxt.Pc)
1129 rel.Add = p.To.Offset
1131 rel.Type = obj.R_CALLMIPS
1133 rel.Type = obj.R_JMPMIPS
1136 case 12: /* movbs r,r */
1141 o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
1142 o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1144 case 13: /* movbu r,r */
1146 o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1148 o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
1151 case 14: /* movwu r,r */
1152 o1 = OP_SRR(opirr(ctxt, -ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1153 o2 = OP_SRR(opirr(ctxt, -ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1155 case 16: /* sll $c,[r1],r2 */
1156 v := regoff(ctxt, &p.From)
1162 /* OP_SRR will use only the low 5 bits of the shift value */
1163 if v >= 32 && vshift(p.As) {
1164 o1 = OP_SRR(opirr(ctxt, -p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
1166 o1 = OP_SRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1169 case 18: /* jmp [r1],0(r2) */
1174 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(0), uint32(p.To.Reg), uint32(r))
1175 rel := obj.Addrel(ctxt.Cursym)
1176 rel.Off = int32(ctxt.Pc)
1178 rel.Type = obj.R_CALLIND
1180 case 19: /* mov $lcon,r ==> lu+or */
1181 v := regoff(ctxt, &p.From)
1182 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1183 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1185 case 20: /* mov lo/hi,r */
1186 a := OP(2, 0) /* mfhi */
1187 if p.From.Reg == REG_LO {
1188 a = OP(2, 2) /* mflo */
1190 o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
1192 case 21: /* mov r,lo/hi */
1193 a := OP(2, 1) /* mthi */
1194 if p.To.Reg == REG_LO {
1195 a = OP(2, 3) /* mtlo */
1197 o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
1199 case 22: /* mul r1,r2 */
1200 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
1202 case 23: /* add $lcon,r1,r2 ==> lu+or+add */
1203 v := regoff(ctxt, &p.From)
1204 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1205 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1210 o3 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1212 case 24: /* mov $ucon,r ==> lu r */
1213 v := regoff(ctxt, &p.From)
1214 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1216 case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
1217 v := regoff(ctxt, &p.From)
1218 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1223 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1225 case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
1226 v := regoff(ctxt, &p.From)
1227 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1228 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1229 r := int(p.From.Reg)
1233 o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1235 case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1236 v := regoff(ctxt, &p.From)
1237 r := int(p.From.Reg)
1247 o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1248 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
1249 o3 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1252 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
1255 case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1256 v := regoff(ctxt, &p.To)
1267 o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1268 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
1269 o3 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1272 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg))
1275 case 30: /* movw r,fr */
1276 a := SP(2, 1) | (4 << 21) /* mtc1 */
1277 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1279 case 31: /* movw fr,r */
1280 a := SP(2, 1) | (0 << 21) /* mtc1 */
1281 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1283 case 32: /* fadd fr1,[fr2],fr3 */
1288 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1290 case 33: /* fabs fr1, fr3 */
1291 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1293 case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
1294 v := regoff(ctxt, &p.From)
1296 if o.a1 == C_ANDCON {
1299 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
1300 o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
1302 case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
1303 v := regoff(ctxt, &p.To)
1308 o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1309 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
1310 o3 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1312 case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
1313 v := regoff(ctxt, &p.From)
1314 r := int(p.From.Reg)
1318 o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1319 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
1320 o3 = OP_IRR(opirr(ctxt, -p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1322 case 37: /* movw r,mr */
1323 a := SP(2, 0) | (4 << 21) /* mtc0 */
1325 a = SP(2, 0) | (5 << 21) /* dmtc0 */
1327 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1329 case 38: /* movw mr,r */
1330 a := SP(2, 0) | (0 << 21) /* mfc0 */
1332 a = SP(2, 0) | (1 << 21) /* dmfc0 */
1334 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1337 o1 = uint32(regoff(ctxt, &p.From))
1339 case 41: /* movw f,fcr */
1340 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */
1341 o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
1343 case 42: /* movw fcr,r */
1344 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
1346 case 47: /* movv r,fr */
1347 a := SP(2, 1) | (5 << 21) /* dmtc1 */
1348 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1350 case 48: /* movv fr,r */
1351 a := SP(2, 1) | (1 << 21) /* dmtc1 */
1352 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1354 case 49: /* undef */
1355 o1 = 52 /* trap -- teq r0, r0 */
1357 /* relocation operations */
1358 case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
1359 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1360 rel := obj.Addrel(ctxt.Cursym)
1361 rel.Off = int32(ctxt.Pc)
1364 rel.Add = p.To.Offset
1365 rel.Type = obj.R_ADDRMIPSU
1366 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1367 o3 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1368 rel2 := obj.Addrel(ctxt.Cursym)
1369 rel2.Off = int32(ctxt.Pc + 8)
1372 rel2.Add = p.To.Offset
1373 rel2.Type = obj.R_ADDRMIPS
1375 case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
1376 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1377 rel := obj.Addrel(ctxt.Cursym)
1378 rel.Off = int32(ctxt.Pc)
1380 rel.Sym = p.From.Sym
1381 rel.Add = p.From.Offset
1382 rel.Type = obj.R_ADDRMIPSU
1383 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1384 o3 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1385 rel2 := obj.Addrel(ctxt.Cursym)
1386 rel2.Off = int32(ctxt.Pc + 8)
1388 rel2.Sym = p.From.Sym
1389 rel2.Add = p.From.Offset
1390 rel2.Type = obj.R_ADDRMIPS
1392 case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
1393 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
1394 rel := obj.Addrel(ctxt.Cursym)
1395 rel.Off = int32(ctxt.Pc)
1397 rel.Sym = p.From.Sym
1398 rel.Add = p.From.Offset
1399 rel.Type = obj.R_ADDRMIPSU
1400 o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
1401 o3 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1402 rel2 := obj.Addrel(ctxt.Cursym)
1403 rel2.Off = int32(ctxt.Pc + 8)
1405 rel2.Sym = p.From.Sym
1406 rel2.Add = p.From.Offset
1407 rel2.Type = obj.R_ADDRMIPS
1409 case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1411 // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
1412 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1413 o2 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
1414 rel := obj.Addrel(ctxt.Cursym)
1415 rel.Off = int32(ctxt.Pc + 4)
1418 rel.Add = p.To.Offset
1419 rel.Type = obj.R_ADDRMIPSTLS
1421 case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1423 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1424 o2 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1425 rel := obj.Addrel(ctxt.Cursym)
1426 rel.Off = int32(ctxt.Pc + 4)
1428 rel.Sym = p.From.Sym
1429 rel.Add = p.From.Offset
1430 rel.Type = obj.R_ADDRMIPSTLS
1432 case 55: /* mov $tlsvar, r ==> rdhwr + add */
1434 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1435 o2 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1436 rel := obj.Addrel(ctxt.Cursym)
1437 rel.Off = int32(ctxt.Pc + 4)
1439 rel.Sym = p.From.Sym
1440 rel.Add = p.From.Offset
1441 rel.Type = obj.R_ADDRMIPSTLS
1451 func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
1454 return ctxt.Instoffset
1457 func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
1458 return int32(vregoff(ctxt, a))
1461 func oprrr(ctxt *obj.Link, a obj.As) uint32 {
1615 ctxt.Diag("bad rrr opcode -%v", obj.Aconv(-a))
1617 ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
1622 func opirr(ctxt *obj.Link, a obj.As) uint32 {
1660 return SP(2, 4) /* likely */
1664 return SP(2, 5) /* likely */
1666 return SP(0, 1) | BCOND(0, 1)
1668 return SP(0, 1) | BCOND(0, 3) /* likely */
1670 return SP(0, 1) | BCOND(2, 1)
1672 return SP(0, 1) | BCOND(2, 3) /* likely */
1676 return SP(2, 7) /* likely */
1680 return SP(2, 6) /* likely */
1682 return SP(0, 1) | BCOND(0, 0)
1684 return SP(0, 1) | BCOND(0, 2) /* likely */
1686 return SP(0, 1) | BCOND(2, 0)
1688 return SP(0, 1) | BCOND(2, 2) /* likely */
1690 return SP(2, 1) | (257 << 16)
1692 return SP(2, 1) | (259 << 16) /* likely */
1694 return SP(2, 1) | (256 << 16)
1696 return SP(2, 1) | (258 << 16) /* likely */
1767 ctxt.Diag("bad irr opcode -%v", obj.Aconv(-a))
1769 ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
1774 func vshift(a obj.As) bool {