]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/obj/mips/asm0.go
4a5ff2f3d42e65700feca4024ad3d6501a7dc604
[gostls13.git] / src / cmd / internal / obj / mips / asm0.go
1 // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
2 //
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.
11 //
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:
18 //
19 // The above copyright notice and this permission notice shall be included in
20 // all copies or substantial portions of the Software.
21 //
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
28 // THE SOFTWARE.
29
30 package mips
31
32 import (
33         "cmd/internal/obj"
34         "fmt"
35         "log"
36         "sort"
37 )
38
39 // Instruction layout.
40
41 const (
42         FuncAlign = 8
43 )
44
45 const (
46         r0iszero = 1
47 )
48
49 type Optab struct {
50         as    obj.As
51         a1    uint8
52         a2    uint8
53         a3    uint8
54         type_ int8
55         size  int8
56         param int16
57 }
58
59 var optab = []Optab{
60         {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
61         {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0},
62
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},
68
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},
75
76         {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
77         {ASLL, C_REG, C_REG, C_REG, 9, 4, 0},
78
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},
85
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},
104
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},
123
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},
149
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},
175
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},
190
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},
195
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},
204
205         {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0},
206
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},
211
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},
216
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},
221
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},
226
227         {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0},
228         {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0},
229
230         {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0},
231
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},
236
237         {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
238         {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
239
240         {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO},
241         {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK},
242
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},
252
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},
264
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},
274
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},
286
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},
291
292         {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0},
293         {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0},
294
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},
299
300         {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0},
301
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},
306
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},
311
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
319
320         {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0},
321 }
322
323 var oprange [ALAST & obj.AMask][]Optab
324
325 var xcmp [C_NCLASS][C_NCLASS]bool
326
327 func span0(ctxt *obj.Link, cursym *obj.LSym) {
328         p := cursym.Text
329         if p == nil || p.Link == nil { // handle external functions and ELF section symbols
330                 return
331         }
332         ctxt.Cursym = cursym
333         ctxt.Autosize = int32(p.To.Offset + 8)
334
335         if oprange[AOR&obj.AMask] == nil {
336                 buildop(ctxt)
337         }
338
339         c := int64(0)
340         p.Pc = c
341
342         var m int
343         var o *Optab
344         for p = p.Link; p != nil; p = p.Link {
345                 ctxt.Curp = p
346                 p.Pc = c
347                 o = oplook(ctxt, p)
348                 m = int(o.size)
349                 if m == 0 {
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)
352                         }
353                         continue
354                 }
355
356                 c += int64(m)
357         }
358
359         cursym.Size = c
360
361         /*
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.
366          */
367         bflag := 1
368
369         var otxt int64
370         var q *obj.Prog
371         for bflag != 0 {
372                 if ctxt.Debugvlog != 0 {
373                         fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
374                 }
375                 bflag = 0
376                 c = 0
377                 for p = cursym.Text.Link; p != nil; p = p.Link {
378                         p.Pc = c
379                         o = oplook(ctxt, p)
380
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 {
385                                         q = ctxt.NewProg()
386                                         q.Link = p.Link
387                                         p.Link = q
388                                         q.As = AJMP
389                                         q.Lineno = p.Lineno
390                                         q.To.Type = obj.TYPE_BRANCH
391                                         q.Pcond = p.Pcond
392                                         p.Pcond = q
393                                         q = ctxt.NewProg()
394                                         q.Link = p.Link
395                                         p.Link = q
396                                         q.As = AJMP
397                                         q.Lineno = p.Lineno
398                                         q.To.Type = obj.TYPE_BRANCH
399                                         q.Pcond = q.Link.Link
400
401                                         addnop(ctxt, p.Link)
402                                         addnop(ctxt, p)
403                                         bflag = 1
404                                 }
405                         }
406
407                         m = int(o.size)
408                         if m == 0 {
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)
411                                 }
412                                 continue
413                         }
414
415                         c += int64(m)
416                 }
417
418                 cursym.Size = c
419         }
420
421         c += -c & (FuncAlign - 1)
422         cursym.Size = c
423
424         /*
425          * lay out the code, emitting code and data relocations.
426          */
427
428         cursym.Grow(cursym.Size)
429
430         bp := cursym.P
431         var i int32
432         var out [4]uint32
433         for p := cursym.Text.Link; p != nil; p = p.Link {
434                 ctxt.Pc = p.Pc
435                 ctxt.Curp = p
436                 o = oplook(ctxt, p)
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)
439                 }
440                 asmout(ctxt, p, o, out[:])
441                 for i = 0; i < int32(o.size/4); i++ {
442                         ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
443                         bp = bp[4:]
444                 }
445         }
446 }
447
448 func isint32(v int64) bool {
449         return int64(int32(v)) == v
450 }
451
452 func isuint32(v uint64) bool {
453         return uint64(uint32(v)) == v
454 }
455
456 func aclass(ctxt *obj.Link, a *obj.Addr) int {
457         switch a.Type {
458         case obj.TYPE_NONE:
459                 return C_NONE
460
461         case obj.TYPE_REG:
462                 if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
463                         return C_REG
464                 }
465                 if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
466                         return C_FREG
467                 }
468                 if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
469                         return C_MREG
470                 }
471                 if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
472                         return C_FCREG
473                 }
474                 if a.Reg == REG_LO {
475                         return C_LO
476                 }
477                 if a.Reg == REG_HI {
478                         return C_HI
479                 }
480                 return C_GOK
481
482         case obj.TYPE_MEM:
483                 switch a.Name {
484                 case obj.NAME_EXTERN,
485                         obj.NAME_STATIC:
486                         if a.Sym == nil {
487                                 break
488                         }
489                         ctxt.Instoffset = a.Offset
490                         if a.Sym != nil { // use relocation
491                                 if a.Sym.Type == obj.STLSBSS {
492                                         return C_TLS
493                                 }
494                                 return C_ADDR
495                         }
496                         return C_LEXT
497
498                 case obj.NAME_AUTO:
499                         ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
500                         if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
501                                 return C_SAUTO
502                         }
503                         return C_LAUTO
504
505                 case obj.NAME_PARAM:
506                         ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
507                         if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
508                                 return C_SAUTO
509                         }
510                         return C_LAUTO
511
512                 case obj.NAME_NONE:
513                         ctxt.Instoffset = a.Offset
514                         if ctxt.Instoffset == 0 {
515                                 return C_ZOREG
516                         }
517                         if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
518                                 return C_SOREG
519                         }
520                         return C_LOREG
521                 }
522
523                 return C_GOK
524
525         case obj.TYPE_TEXTSIZE:
526                 return C_TEXTSIZE
527
528         case obj.TYPE_CONST,
529                 obj.TYPE_ADDR:
530                 switch a.Name {
531                 case obj.NAME_NONE:
532                         ctxt.Instoffset = a.Offset
533                         if a.Reg != 0 {
534                                 if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
535                                         return C_SACON
536                                 }
537                                 if isint32(ctxt.Instoffset) {
538                                         return C_LACON
539                                 }
540                                 return C_DACON
541                         }
542
543                         goto consize
544
545                 case obj.NAME_EXTERN,
546                         obj.NAME_STATIC:
547                         s := a.Sym
548                         if s == nil {
549                                 break
550                         }
551                         if s.Type == obj.SCONST {
552                                 ctxt.Instoffset = a.Offset
553                                 goto consize
554                         }
555
556                         ctxt.Instoffset = a.Offset
557                         if s.Type == obj.STLSBSS {
558                                 return C_STCON // address of TLS variable
559                         }
560                         return C_LECON
561
562                 case obj.NAME_AUTO:
563                         ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
564                         if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
565                                 return C_SACON
566                         }
567                         return C_LACON
568
569                 case obj.NAME_PARAM:
570                         ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
571                         if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
572                                 return C_SACON
573                         }
574                         return C_LACON
575                 }
576
577                 return C_GOK
578
579         consize:
580                 if ctxt.Instoffset >= 0 {
581                         if ctxt.Instoffset == 0 {
582                                 return C_ZCON
583                         }
584                         if ctxt.Instoffset <= 0x7fff {
585                                 return C_SCON
586                         }
587                         if ctxt.Instoffset <= 0xffff {
588                                 return C_ANDCON
589                         }
590                         if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
591                                 return C_UCON
592                         }
593                         if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
594                                 return C_LCON
595                         }
596                         return C_LCON // C_DCON
597                 }
598
599                 if ctxt.Instoffset >= -0x8000 {
600                         return C_ADDCON
601                 }
602                 if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
603                         return C_UCON
604                 }
605                 if isint32(ctxt.Instoffset) {
606                         return C_LCON
607                 }
608                 return C_LCON // C_DCON
609
610         case obj.TYPE_BRANCH:
611                 return C_SBRA
612         }
613
614         return C_GOK
615 }
616
617 func prasm(p *obj.Prog) {
618         fmt.Printf("%v\n", p)
619 }
620
621 func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
622         if oprange[AOR&obj.AMask] == nil {
623                 buildop(ctxt)
624         }
625
626         a1 := int(p.Optab)
627         if a1 != 0 {
628                 return &optab[a1-1]
629         }
630         a1 = int(p.From.Class)
631         if a1 == 0 {
632                 a1 = aclass(ctxt, &p.From) + 1
633                 p.From.Class = int8(a1)
634         }
635
636         a1--
637         a3 := int(p.To.Class)
638         if a3 == 0 {
639                 a3 = aclass(ctxt, &p.To) + 1
640                 p.To.Class = int8(a3)
641         }
642
643         a3--
644         a2 := C_NONE
645         if p.Reg != 0 {
646                 a2 = C_REG
647         }
648
649         //print("oplook %P %d %d %d\n", p, a1, a2, a3);
650
651         ops := oprange[p.As&obj.AMask]
652         c1 := &xcmp[a1]
653         c3 := &xcmp[a3]
654         for i := range ops {
655                 op := &ops[i]
656                 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
657                         p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
658                         return op
659                 }
660         }
661
662         ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3))
663         prasm(p)
664         if ops == nil {
665                 ops = optab
666         }
667         return &ops[0]
668 }
669
670 func cmp(a int, b int) bool {
671         if a == b {
672                 return true
673         }
674         switch a {
675         case C_LCON:
676                 if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
677                         return true
678                 }
679
680         case C_ADD0CON:
681                 if b == C_ADDCON {
682                         return true
683                 }
684                 fallthrough
685
686         case C_ADDCON:
687                 if b == C_ZCON || b == C_SCON {
688                         return true
689                 }
690
691         case C_AND0CON:
692                 if b == C_ANDCON {
693                         return true
694                 }
695                 fallthrough
696
697         case C_ANDCON:
698                 if b == C_ZCON || b == C_SCON {
699                         return true
700                 }
701
702         case C_UCON:
703                 if b == C_ZCON {
704                         return true
705                 }
706
707         case C_SCON:
708                 if b == C_ZCON {
709                         return true
710                 }
711
712         case C_LACON:
713                 if b == C_SACON {
714                         return true
715                 }
716
717         case C_LBRA:
718                 if b == C_SBRA {
719                         return true
720                 }
721
722         case C_LEXT:
723                 if b == C_SEXT {
724                         return true
725                 }
726
727         case C_LAUTO:
728                 if b == C_SAUTO {
729                         return true
730                 }
731
732         case C_REG:
733                 if b == C_ZCON {
734                         return r0iszero != 0 /*TypeKind(100016)*/
735                 }
736
737         case C_LOREG:
738                 if b == C_ZOREG || b == C_SOREG {
739                         return true
740                 }
741
742         case C_SOREG:
743                 if b == C_ZOREG {
744                         return true
745                 }
746         }
747
748         return false
749 }
750
751 type ocmp []Optab
752
753 func (x ocmp) Len() int {
754         return len(x)
755 }
756
757 func (x ocmp) Swap(i, j int) {
758         x[i], x[j] = x[j], x[i]
759 }
760
761 func (x ocmp) Less(i, j int) bool {
762         p1 := &x[i]
763         p2 := &x[j]
764         n := int(p1.as) - int(p2.as)
765         if n != 0 {
766                 return n < 0
767         }
768         n = int(p1.a1) - int(p2.a1)
769         if n != 0 {
770                 return n < 0
771         }
772         n = int(p1.a2) - int(p2.a2)
773         if n != 0 {
774                 return n < 0
775         }
776         n = int(p1.a3) - int(p2.a3)
777         if n != 0 {
778                 return n < 0
779         }
780         return false
781 }
782
783 func opset(a, b0 obj.As) {
784         oprange[a&obj.AMask] = oprange[b0]
785 }
786
787 func buildop(ctxt *obj.Link) {
788         var n int
789
790         for i := 0; i < C_NCLASS; i++ {
791                 for n = 0; n < C_NCLASS; n++ {
792                         if cmp(n, i) {
793                                 xcmp[i][n] = true
794                         }
795                 }
796         }
797         for n = 0; optab[n].as != obj.AXXX; n++ {
798         }
799         sort.Sort(ocmp(optab[:n]))
800         for i := 0; i < n; i++ {
801                 r := optab[i].as
802                 r0 := r & obj.AMask
803                 start := i
804                 for optab[i].as == r {
805                         i++
806                 }
807                 oprange[r0] = optab[start:i]
808                 i--
809
810                 switch r {
811                 default:
812                         ctxt.Diag("unknown op in build: %v", obj.Aconv(r))
813                         log.Fatalf("bad code")
814
815                 case AABSF:
816                         opset(AMOVFD, r0)
817                         opset(AMOVDF, r0)
818                         opset(AMOVWF, r0)
819                         opset(AMOVFW, r0)
820                         opset(AMOVWD, r0)
821                         opset(AMOVDW, r0)
822                         opset(ANEGF, r0)
823                         opset(ANEGD, r0)
824                         opset(AABSD, r0)
825                         opset(ATRUNCDW, r0)
826                         opset(ATRUNCFW, r0)
827                         opset(ATRUNCDV, r0)
828                         opset(ATRUNCFV, r0)
829                         opset(AMOVVF, r0)
830                         opset(AMOVFV, r0)
831                         opset(AMOVVD, r0)
832                         opset(AMOVDV, r0)
833
834                 case AADD:
835                         opset(ASGT, r0)
836                         opset(ASGTU, r0)
837                         opset(AADDU, r0)
838                         opset(AADDV, r0)
839                         opset(AADDVU, r0)
840
841                 case AADDF:
842                         opset(ADIVF, r0)
843                         opset(ADIVD, r0)
844                         opset(AMULF, r0)
845                         opset(AMULD, r0)
846                         opset(ASUBF, r0)
847                         opset(ASUBD, r0)
848                         opset(AADDD, r0)
849
850                 case AAND:
851                         opset(AOR, r0)
852                         opset(AXOR, r0)
853
854                 case ABEQ:
855                         opset(ABNE, r0)
856
857                 case ABLEZ:
858                         opset(ABGEZ, r0)
859                         opset(ABGEZAL, r0)
860                         opset(ABLTZ, r0)
861                         opset(ABLTZAL, r0)
862                         opset(ABGTZ, r0)
863
864                 case AMOVB:
865                         opset(AMOVH, r0)
866
867                 case AMOVBU:
868                         opset(AMOVHU, r0)
869
870                 case AMUL:
871                         opset(AREM, r0)
872                         opset(AREMU, r0)
873                         opset(ADIVU, r0)
874                         opset(AMULU, r0)
875                         opset(ADIV, r0)
876                         opset(ADIVV, r0)
877                         opset(ADIVVU, r0)
878                         opset(AMULV, r0)
879                         opset(AMULVU, r0)
880                         opset(AREMV, r0)
881                         opset(AREMVU, r0)
882
883                 case ASLL:
884                         opset(ASRL, r0)
885                         opset(ASRA, r0)
886                         opset(ASLLV, r0)
887                         opset(ASRAV, r0)
888                         opset(ASRLV, r0)
889
890                 case ASUB:
891                         opset(ASUBU, r0)
892                         opset(ASUBV, r0)
893                         opset(ASUBVU, r0)
894                         opset(ANOR, r0)
895
896                 case ASYSCALL:
897                         opset(ATLBP, r0)
898                         opset(ATLBR, r0)
899                         opset(ATLBWI, r0)
900                         opset(ATLBWR, r0)
901
902                 case ACMPEQF:
903                         opset(ACMPGTF, r0)
904                         opset(ACMPGTD, r0)
905                         opset(ACMPGEF, r0)
906                         opset(ACMPGED, r0)
907                         opset(ACMPEQD, r0)
908
909                 case ABFPT:
910                         opset(ABFPF, r0)
911
912                 case AMOVWL:
913                         opset(AMOVWR, r0)
914                         opset(AMOVVR, r0)
915                         opset(AMOVVL, r0)
916
917                 case AMOVW,
918                         AMOVD,
919                         AMOVF,
920                         AMOVV,
921                         ABREAK,
922                         ARFE,
923                         AJAL,
924                         AJMP,
925                         AMOVWU,
926                         AWORD,
927                         obj.ANOP,
928                         obj.ATEXT,
929                         obj.AUNDEF,
930                         obj.AUSEFIELD,
931                         obj.AFUNCDATA,
932                         obj.APCDATA,
933                         obj.ADUFFZERO,
934                         obj.ADUFFCOPY:
935                         break
936                 }
937         }
938 }
939
940 func OP(x uint32, y uint32) uint32 {
941         return x<<3 | y<<0
942 }
943
944 func SP(x uint32, y uint32) uint32 {
945         return x<<29 | y<<26
946 }
947
948 func BCOND(x uint32, y uint32) uint32 {
949         return x<<19 | y<<16
950 }
951
952 func MMU(x uint32, y uint32) uint32 {
953         return SP(2, 0) | 16<<21 | x<<3 | y<<0
954 }
955
956 func FPF(x uint32, y uint32) uint32 {
957         return SP(2, 1) | 16<<21 | x<<3 | y<<0
958 }
959
960 func FPD(x uint32, y uint32) uint32 {
961         return SP(2, 1) | 17<<21 | x<<3 | y<<0
962 }
963
964 func FPW(x uint32, y uint32) uint32 {
965         return SP(2, 1) | 20<<21 | x<<3 | y<<0
966 }
967
968 func FPV(x uint32, y uint32) uint32 {
969         return SP(2, 1) | 21<<21 | x<<3 | y<<0
970 }
971
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
974 }
975
976 func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
977         return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
978 }
979
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
982 }
983
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
986 }
987
988 func OP_JMP(op uint32, i uint32) uint32 {
989         return op | i&0x3FFFFFF
990 }
991
992 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
993         o1 := uint32(0)
994         o2 := uint32(0)
995         o3 := uint32(0)
996         o4 := uint32(0)
997
998         switch o.type_ {
999         default:
1000                 ctxt.Diag("unknown type %d %v", o.type_)
1001                 prasm(p)
1002
1003         case 0: /* pseudo ops */
1004                 break
1005
1006         case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
1007                 a := AOR
1008                 if p.As == AMOVW {
1009                         a = AADDU // sign-extended to high 32 bits
1010                 }
1011                 o1 = OP_RRR(oprrr(ctxt, a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
1012
1013         case 2: /* add/sub r1,[r2],r3 */
1014                 r := int(p.Reg)
1015
1016                 if r == 0 {
1017                         r = int(p.To.Reg)
1018                 }
1019                 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1020
1021         case 3: /* mov $soreg, r ==> or/add $i,o,r */
1022                 v := regoff(ctxt, &p.From)
1023
1024                 r := int(p.From.Reg)
1025                 if r == 0 {
1026                         r = int(o.param)
1027                 }
1028                 a := AADDVU
1029                 if o.a1 == C_ANDCON {
1030                         a = AOR
1031                 }
1032
1033                 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
1034
1035         case 4: /* add $scon,[r1],r2 */
1036                 v := regoff(ctxt, &p.From)
1037
1038                 r := int(p.Reg)
1039                 if r == 0 {
1040                         r = int(p.To.Reg)
1041                 }
1042
1043                 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1044
1045         case 5: /* syscall */
1046                 o1 = oprrr(ctxt, p.As)
1047
1048         case 6: /* beq r1,[r2],sbra */
1049                 v := int32(0)
1050                 if p.Pcond == nil {
1051                         v = int32(-4) >> 2
1052                 } else {
1053                         v = int32(p.Pcond.Pc-p.Pc-4) >> 2
1054                 }
1055                 if (v<<16)>>16 != v {
1056                         ctxt.Diag("short branch too far\n%v", p)
1057                 }
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.
1061                 o2 = 0
1062
1063         case 7: /* mov r, soreg ==> sw o(r) */
1064                 r := int(p.To.Reg)
1065                 if r == 0 {
1066                         r = int(o.param)
1067                 }
1068                 v := regoff(ctxt, &p.To)
1069                 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1070
1071         case 8: /* mov soreg, r ==> lw o(r) */
1072                 r := int(p.From.Reg)
1073                 if r == 0 {
1074                         r = int(o.param)
1075                 }
1076                 v := regoff(ctxt, &p.From)
1077                 o1 = OP_IRR(opirr(ctxt, -p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1078
1079         case 9: /* sll r1,[r2],r3 */
1080                 r := int(p.Reg)
1081
1082                 if r == 0 {
1083                         r = int(p.To.Reg)
1084                 }
1085                 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
1086
1087         case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
1088                 v := regoff(ctxt, &p.From)
1089                 a := AOR
1090                 if v < 0 {
1091                         a = AADDU
1092                 }
1093                 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
1094                 r := int(p.Reg)
1095                 if r == 0 {
1096                         r = int(p.To.Reg)
1097                 }
1098                 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1099
1100         case 11: /* jmp lbra */
1101                 v := int32(0)
1102                 if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
1103                         // use PC-relative branch for short branches
1104                         // BEQ  R0, R0, sbra
1105                         if p.Pcond == nil {
1106                                 v = int32(-4) >> 2
1107                         } else {
1108                                 v = int32(p.Pcond.Pc-p.Pc-4) >> 2
1109                         }
1110                         if (v<<16)>>16 == v {
1111                                 o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
1112                                 break
1113                         }
1114                 }
1115                 if p.Pcond == nil {
1116                         v = int32(p.Pc) >> 2
1117                 } else {
1118                         v = int32(p.Pcond.Pc) >> 2
1119                 }
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
1124                 }
1125                 rel := obj.Addrel(ctxt.Cursym)
1126                 rel.Off = int32(ctxt.Pc)
1127                 rel.Siz = 4
1128                 rel.Sym = p.To.Sym
1129                 rel.Add = p.To.Offset
1130                 if p.As == AJAL {
1131                         rel.Type = obj.R_CALLMIPS
1132                 } else {
1133                         rel.Type = obj.R_JMPMIPS
1134                 }
1135
1136         case 12: /* movbs r,r */
1137                 v := 16
1138                 if p.As == AMOVB {
1139                         v = 24
1140                 }
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))
1143
1144         case 13: /* movbu r,r */
1145                 if p.As == AMOVBU {
1146                         o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1147                 } else {
1148                         o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
1149                 }
1150
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))
1154
1155         case 16: /* sll $c,[r1],r2 */
1156                 v := regoff(ctxt, &p.From)
1157                 r := int(p.Reg)
1158                 if r == 0 {
1159                         r = int(p.To.Reg)
1160                 }
1161
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))
1165                 } else {
1166                         o1 = OP_SRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1167                 }
1168
1169         case 18: /* jmp [r1],0(r2) */
1170                 r := int(p.Reg)
1171                 if r == 0 {
1172                         r = int(o.param)
1173                 }
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)
1177                 rel.Siz = 0
1178                 rel.Type = obj.R_CALLIND
1179
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))
1184
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 */
1189                 }
1190                 o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
1191
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 */
1196                 }
1197                 o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
1198
1199         case 22: /* mul r1,r2 */
1200                 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
1201
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))
1206                 r := int(p.Reg)
1207                 if r == 0 {
1208                         r = int(p.To.Reg)
1209                 }
1210                 o3 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1211
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))
1215
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))
1219                 r := int(p.Reg)
1220                 if r == 0 {
1221                         r = int(p.To.Reg)
1222                 }
1223                 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1224
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)
1230                 if r == 0 {
1231                         r = int(o.param)
1232                 }
1233                 o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1234
1235         case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1236                 v := regoff(ctxt, &p.From)
1237                 r := int(p.From.Reg)
1238                 if r == 0 {
1239                         r = int(o.param)
1240                 }
1241                 a := -AMOVF
1242                 if p.As == AMOVD {
1243                         a = -AMOVD
1244                 }
1245                 switch o.size {
1246                 case 12:
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))
1250
1251                 case 4:
1252                         o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
1253                 }
1254
1255         case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1256                 v := regoff(ctxt, &p.To)
1257                 r := int(p.To.Reg)
1258                 if r == 0 {
1259                         r = int(o.param)
1260                 }
1261                 a := AMOVF
1262                 if p.As == AMOVD {
1263                         a = AMOVD
1264                 }
1265                 switch o.size {
1266                 case 12:
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))
1270
1271                 case 4:
1272                         o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg))
1273                 }
1274
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))
1278
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))
1282
1283         case 32: /* fadd fr1,[fr2],fr3 */
1284                 r := int(p.Reg)
1285                 if r == 0 {
1286                         r = int(p.To.Reg)
1287                 }
1288                 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1289
1290         case 33: /* fabs fr1, fr3 */
1291                 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1292
1293         case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
1294                 v := regoff(ctxt, &p.From)
1295                 a := AADDU
1296                 if o.a1 == C_ANDCON {
1297                         a = AOR
1298                 }
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 */
1301
1302         case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
1303                 v := regoff(ctxt, &p.To)
1304                 r := int(p.To.Reg)
1305                 if r == 0 {
1306                         r = int(o.param)
1307                 }
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))
1311
1312         case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
1313                 v := regoff(ctxt, &p.From)
1314                 r := int(p.From.Reg)
1315                 if r == 0 {
1316                         r = int(o.param)
1317                 }
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))
1321
1322         case 37: /* movw r,mr */
1323                 a := SP(2, 0) | (4 << 21) /* mtc0 */
1324                 if p.As == AMOVV {
1325                         a = SP(2, 0) | (5 << 21) /* dmtc0 */
1326                 }
1327                 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1328
1329         case 38: /* movw mr,r */
1330                 a := SP(2, 0) | (0 << 21) /* mfc0 */
1331                 if p.As == AMOVV {
1332                         a = SP(2, 0) | (1 << 21) /* dmfc0 */
1333                 }
1334                 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1335
1336         case 40: /* word */
1337                 o1 = uint32(regoff(ctxt, &p.From))
1338
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 */
1342
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 */
1345
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))
1349
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))
1353
1354         case 49: /* undef */
1355                 o1 = 52 /* trap -- teq r0, r0 */
1356
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)
1362                 rel.Siz = 4
1363                 rel.Sym = p.To.Sym
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)
1370                 rel2.Siz = 4
1371                 rel2.Sym = p.To.Sym
1372                 rel2.Add = p.To.Offset
1373                 rel2.Type = obj.R_ADDRMIPS
1374
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)
1379                 rel.Siz = 4
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)
1387                 rel2.Siz = 4
1388                 rel2.Sym = p.From.Sym
1389                 rel2.Add = p.From.Offset
1390                 rel2.Type = obj.R_ADDRMIPS
1391
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)
1396                 rel.Siz = 4
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)
1404                 rel2.Siz = 4
1405                 rel2.Sym = p.From.Sym
1406                 rel2.Add = p.From.Offset
1407                 rel2.Type = obj.R_ADDRMIPS
1408
1409         case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1410                 // clobbers 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)
1416                 rel.Siz = 4
1417                 rel.Sym = p.To.Sym
1418                 rel.Add = p.To.Offset
1419                 rel.Type = obj.R_ADDRMIPSTLS
1420
1421         case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1422                 // clobbers 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)
1427                 rel.Siz = 4
1428                 rel.Sym = p.From.Sym
1429                 rel.Add = p.From.Offset
1430                 rel.Type = obj.R_ADDRMIPSTLS
1431
1432         case 55: /* mov $tlsvar, r ==> rdhwr + add */
1433                 // clobbers R3 !
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)
1438                 rel.Siz = 4
1439                 rel.Sym = p.From.Sym
1440                 rel.Add = p.From.Offset
1441                 rel.Type = obj.R_ADDRMIPSTLS
1442         }
1443
1444         out[0] = o1
1445         out[1] = o2
1446         out[2] = o3
1447         out[3] = o4
1448         return
1449 }
1450
1451 func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
1452         ctxt.Instoffset = 0
1453         aclass(ctxt, a)
1454         return ctxt.Instoffset
1455 }
1456
1457 func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
1458         return int32(vregoff(ctxt, a))
1459 }
1460
1461 func oprrr(ctxt *obj.Link, a obj.As) uint32 {
1462         switch a {
1463         case AADD:
1464                 return OP(4, 0)
1465         case AADDU:
1466                 return OP(4, 1)
1467         case ASGT:
1468                 return OP(5, 2)
1469         case ASGTU:
1470                 return OP(5, 3)
1471         case AAND:
1472                 return OP(4, 4)
1473         case AOR:
1474                 return OP(4, 5)
1475         case AXOR:
1476                 return OP(4, 6)
1477         case ASUB:
1478                 return OP(4, 2)
1479         case ASUBU:
1480                 return OP(4, 3)
1481         case ANOR:
1482                 return OP(4, 7)
1483         case ASLL:
1484                 return OP(0, 4)
1485         case ASRL:
1486                 return OP(0, 6)
1487         case ASRA:
1488                 return OP(0, 7)
1489         case ASLLV:
1490                 return OP(2, 4)
1491         case ASRLV:
1492                 return OP(2, 6)
1493         case ASRAV:
1494                 return OP(2, 7)
1495         case AADDV:
1496                 return OP(5, 4)
1497         case AADDVU:
1498                 return OP(5, 5)
1499         case ASUBV:
1500                 return OP(5, 6)
1501         case ASUBVU:
1502                 return OP(5, 7)
1503         case AREM,
1504                 ADIV:
1505                 return OP(3, 2)
1506         case AREMU,
1507                 ADIVU:
1508                 return OP(3, 3)
1509         case AMUL:
1510                 return OP(3, 0)
1511         case AMULU:
1512                 return OP(3, 1)
1513         case AREMV,
1514                 ADIVV:
1515                 return OP(3, 6)
1516         case AREMVU,
1517                 ADIVVU:
1518                 return OP(3, 7)
1519         case AMULV:
1520                 return OP(3, 4)
1521         case AMULVU:
1522                 return OP(3, 5)
1523
1524         case AJMP:
1525                 return OP(1, 0)
1526         case AJAL:
1527                 return OP(1, 1)
1528
1529         case ABREAK:
1530                 return OP(1, 5)
1531         case ASYSCALL:
1532                 return OP(1, 4)
1533         case ATLBP:
1534                 return MMU(1, 0)
1535         case ATLBR:
1536                 return MMU(0, 1)
1537         case ATLBWI:
1538                 return MMU(0, 2)
1539         case ATLBWR:
1540                 return MMU(0, 6)
1541         case ARFE:
1542                 return MMU(2, 0)
1543
1544         case ADIVF:
1545                 return FPF(0, 3)
1546         case ADIVD:
1547                 return FPD(0, 3)
1548         case AMULF:
1549                 return FPF(0, 2)
1550         case AMULD:
1551                 return FPD(0, 2)
1552         case ASUBF:
1553                 return FPF(0, 1)
1554         case ASUBD:
1555                 return FPD(0, 1)
1556         case AADDF:
1557                 return FPF(0, 0)
1558         case AADDD:
1559                 return FPD(0, 0)
1560         case ATRUNCFV:
1561                 return FPF(1, 1)
1562         case ATRUNCDV:
1563                 return FPD(1, 1)
1564         case ATRUNCFW:
1565                 return FPF(1, 5)
1566         case ATRUNCDW:
1567                 return FPD(1, 5)
1568         case AMOVFV:
1569                 return FPF(4, 5)
1570         case AMOVDV:
1571                 return FPD(4, 5)
1572         case AMOVVF:
1573                 return FPV(4, 0)
1574         case AMOVVD:
1575                 return FPV(4, 1)
1576         case AMOVFW:
1577                 return FPF(4, 4)
1578         case AMOVDW:
1579                 return FPD(4, 4)
1580         case AMOVWF:
1581                 return FPW(4, 0)
1582         case AMOVDF:
1583                 return FPD(4, 0)
1584         case AMOVWD:
1585                 return FPW(4, 1)
1586         case AMOVFD:
1587                 return FPF(4, 1)
1588         case AABSF:
1589                 return FPF(0, 5)
1590         case AABSD:
1591                 return FPD(0, 5)
1592         case AMOVF:
1593                 return FPF(0, 6)
1594         case AMOVD:
1595                 return FPD(0, 6)
1596         case ANEGF:
1597                 return FPF(0, 7)
1598         case ANEGD:
1599                 return FPD(0, 7)
1600         case ACMPEQF:
1601                 return FPF(6, 2)
1602         case ACMPEQD:
1603                 return FPD(6, 2)
1604         case ACMPGTF:
1605                 return FPF(7, 4)
1606         case ACMPGTD:
1607                 return FPD(7, 4)
1608         case ACMPGEF:
1609                 return FPF(7, 6)
1610         case ACMPGED:
1611                 return FPD(7, 6)
1612         }
1613
1614         if a < 0 {
1615                 ctxt.Diag("bad rrr opcode -%v", obj.Aconv(-a))
1616         } else {
1617                 ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
1618         }
1619         return 0
1620 }
1621
1622 func opirr(ctxt *obj.Link, a obj.As) uint32 {
1623         switch a {
1624         case AADD:
1625                 return SP(1, 0)
1626         case AADDU:
1627                 return SP(1, 1)
1628         case ASGT:
1629                 return SP(1, 2)
1630         case ASGTU:
1631                 return SP(1, 3)
1632         case AAND:
1633                 return SP(1, 4)
1634         case AOR:
1635                 return SP(1, 5)
1636         case AXOR:
1637                 return SP(1, 6)
1638         case ALUI:
1639                 return SP(1, 7)
1640         case ASLL:
1641                 return OP(0, 0)
1642         case ASRL:
1643                 return OP(0, 2)
1644         case ASRA:
1645                 return OP(0, 3)
1646         case AADDV:
1647                 return SP(3, 0)
1648         case AADDVU:
1649                 return SP(3, 1)
1650
1651         case AJMP:
1652                 return SP(0, 2)
1653         case AJAL,
1654                 obj.ADUFFZERO,
1655                 obj.ADUFFCOPY:
1656                 return SP(0, 3)
1657         case ABEQ:
1658                 return SP(0, 4)
1659         case -ABEQ:
1660                 return SP(2, 4) /* likely */
1661         case ABNE:
1662                 return SP(0, 5)
1663         case -ABNE:
1664                 return SP(2, 5) /* likely */
1665         case ABGEZ:
1666                 return SP(0, 1) | BCOND(0, 1)
1667         case -ABGEZ:
1668                 return SP(0, 1) | BCOND(0, 3) /* likely */
1669         case ABGEZAL:
1670                 return SP(0, 1) | BCOND(2, 1)
1671         case -ABGEZAL:
1672                 return SP(0, 1) | BCOND(2, 3) /* likely */
1673         case ABGTZ:
1674                 return SP(0, 7)
1675         case -ABGTZ:
1676                 return SP(2, 7) /* likely */
1677         case ABLEZ:
1678                 return SP(0, 6)
1679         case -ABLEZ:
1680                 return SP(2, 6) /* likely */
1681         case ABLTZ:
1682                 return SP(0, 1) | BCOND(0, 0)
1683         case -ABLTZ:
1684                 return SP(0, 1) | BCOND(0, 2) /* likely */
1685         case ABLTZAL:
1686                 return SP(0, 1) | BCOND(2, 0)
1687         case -ABLTZAL:
1688                 return SP(0, 1) | BCOND(2, 2) /* likely */
1689         case ABFPT:
1690                 return SP(2, 1) | (257 << 16)
1691         case -ABFPT:
1692                 return SP(2, 1) | (259 << 16) /* likely */
1693         case ABFPF:
1694                 return SP(2, 1) | (256 << 16)
1695         case -ABFPF:
1696                 return SP(2, 1) | (258 << 16) /* likely */
1697
1698         case AMOVB,
1699                 AMOVBU:
1700                 return SP(5, 0)
1701         case AMOVH,
1702                 AMOVHU:
1703                 return SP(5, 1)
1704         case AMOVW,
1705                 AMOVWU:
1706                 return SP(5, 3)
1707         case AMOVV:
1708                 return SP(7, 7)
1709         case AMOVF:
1710                 return SP(7, 1)
1711         case AMOVD:
1712                 return SP(7, 5)
1713         case AMOVWL:
1714                 return SP(5, 2)
1715         case AMOVWR:
1716                 return SP(5, 6)
1717         case AMOVVL:
1718                 return SP(5, 4)
1719         case AMOVVR:
1720                 return SP(5, 5)
1721
1722         case ABREAK:
1723                 return SP(5, 7)
1724
1725         case -AMOVWL:
1726                 return SP(4, 2)
1727         case -AMOVWR:
1728                 return SP(4, 6)
1729         case -AMOVVL:
1730                 return SP(3, 2)
1731         case -AMOVVR:
1732                 return SP(3, 3)
1733         case -AMOVB:
1734                 return SP(4, 0)
1735         case -AMOVBU:
1736                 return SP(4, 4)
1737         case -AMOVH:
1738                 return SP(4, 1)
1739         case -AMOVHU:
1740                 return SP(4, 5)
1741         case -AMOVW:
1742                 return SP(4, 3)
1743         case -AMOVWU:
1744                 return SP(4, 7)
1745         case -AMOVV:
1746                 return SP(6, 7)
1747         case -AMOVF:
1748                 return SP(6, 1)
1749         case -AMOVD:
1750                 return SP(6, 5)
1751
1752         case ASLLV:
1753                 return OP(7, 0)
1754         case ASRLV:
1755                 return OP(7, 2)
1756         case ASRAV:
1757                 return OP(7, 3)
1758         case -ASLLV:
1759                 return OP(7, 4)
1760         case -ASRLV:
1761                 return OP(7, 6)
1762         case -ASRAV:
1763                 return OP(7, 7)
1764         }
1765
1766         if a < 0 {
1767                 ctxt.Diag("bad irr opcode -%v", obj.Aconv(-a))
1768         } else {
1769                 ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
1770         }
1771         return 0
1772 }
1773
1774 func vshift(a obj.As) bool {
1775         switch a {
1776         case ASLLV,
1777                 ASRLV,
1778                 ASRAV:
1779                 return true
1780         }
1781         return false
1782 }