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
30package mips
31
32import (
33	"cmd/internal/obj"
34	"cmd/internal/objabi"
35	"cmd/internal/sys"
36	"fmt"
37	"log"
38	"sort"
39)
40
41// ctxt0 holds state while assembling a single function.
42// Each function gets a fresh ctxt0.
43// This allows for multiple functions to be safely concurrently assembled.
44type ctxt0 struct {
45	ctxt       *obj.Link
46	newprog    obj.ProgAlloc
47	cursym     *obj.LSym
48	autosize   int32
49	instoffset int64
50	pc         int64
51}
52
53// Instruction layout.
54
55const (
56	mips64FuncAlign = 8
57)
58
59const (
60	r0iszero = 1
61)
62
63type Optab struct {
64	as     obj.As
65	a1     uint8
66	a2     uint8
67	a3     uint8
68	type_  int8
69	size   int8
70	param  int16
71	family sys.ArchFamily // 0 means both sys.MIPS and sys.MIPS64
72	flag   uint8
73}
74
75const (
76	// Optab.flag
77	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
78)
79
80var optab = []Optab{
81	{obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0, sys.MIPS64, 0},
82	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
83
84	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
85	{AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0, sys.MIPS64, 0},
86	{AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0, 0, NOTUSETMP},
87	{AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0, 0, 0},
88	{AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0, sys.MIPS64, NOTUSETMP},
89
90	{ASUB, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
91	{ASUBV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
92	{AADD, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
93	{AADDV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
94	{AAND, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
95	{ASUB, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
96	{ASUBV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
97	{AADD, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
98	{AADDV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
99	{AAND, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
100	{ACMOVN, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
101	{ANEGW, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
102	{ANEGV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
103
104	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
105	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
106	{ASLLV, C_REG, C_NONE, C_REG, 9, 4, 0, sys.MIPS64, 0},
107	{ASLLV, C_REG, C_REG, C_REG, 9, 4, 0, sys.MIPS64, 0},
108	{ACLO, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
109
110	{AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0, 0, 0},
111	{AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0, 0, 0},
112	{ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0, 0, 0},
113	{AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
114	{AMOVVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, sys.MIPS64, 0},
115	{AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
116	{AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
117
118	{AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
119	{AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
120	{AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
121	{AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
122	{AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
123	{AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
124	{AMOVVL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
125	{AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
126	{AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
127	{AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
128	{AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
129	{AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
130	{AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
131	{AMOVVL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
132	{AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
133	{AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
134	{AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
135	{AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
136	{AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
137	{AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
138	{AMOVVL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
139	{ASC, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
140	{ASCV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
141
142	{AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
143	{AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
144	{AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
145	{AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
146	{AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
147	{AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
148	{AMOVVL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
149	{AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
150	{AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
151	{AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
152	{AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
153	{AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
154	{AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
155	{AMOVVL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
156	{AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
157	{AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
158	{AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
159	{AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
160	{AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
161	{AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
162	{AMOVVL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
163	{ALL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
164	{ALLV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
165
166	{AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
167	{AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
168	{AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
169	{AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
170	{AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
171	{AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
172	{AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
173	{AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
174	{AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
175	{AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
176	{AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
177	{AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
178	{AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
179	{AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
180	{AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
181	{ASC, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
182	{AMOVW, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
183	{AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
184	{AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
185	{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
186	{AMOVB, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
187	{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
188	{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
189	{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
190	{AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
191	{AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
192	{AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
193	{AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
194	{AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
195
196	{AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
197	{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
198	{AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
199	{AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
200	{AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
201	{AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
202	{AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
203	{AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
204	{AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
205	{AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
206	{AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
207	{AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
208	{AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
209	{AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
210	{AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
211	{AMOVW, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
212	{AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
213	{AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
214	{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
215	{AMOVB, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
216	{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
217	{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
218	{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
219	{AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
220	{AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
221	{AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
222	{AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
223	{AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
224
225	{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
226	{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
227	{AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP, 0, 0},
228	{AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP, sys.MIPS64, 0},
229	{AMOVW, C_LECON, C_NONE, C_REG, 52, 8, REGSB, sys.MIPS, NOTUSETMP},
230	{AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
231	{AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
232
233	{AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP, 0, 0},
234	{AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP, sys.MIPS64, 0},
235	{AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
236	{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
237	{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
238	{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
239	{AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0, 0, NOTUSETMP},
240	{AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0, sys.MIPS64, NOTUSETMP},
241
242	{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0, 0, 0},
243	{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0, sys.MIPS64, 0},
244	{AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0, 0, NOTUSETMP},
245	{AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0, sys.MIPS64, NOTUSETMP},
246
247	{AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0, 0, 0},
248	{AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
249	{AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0, 0, 0},
250	{AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
251	{AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0, 0, 0},
252	{AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0, sys.MIPS64, 0},
253	{AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0, 0, 0},
254	{AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0, sys.MIPS64, 0},
255
256	{AMUL, C_REG, C_REG, C_NONE, 22, 4, 0, 0, 0},
257	{AMUL, C_REG, C_REG, C_REG, 22, 4, 0, 0, 0},
258	{AMULV, C_REG, C_REG, C_NONE, 22, 4, 0, sys.MIPS64, 0},
259
260	{AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
261	{AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
262	{AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
263	{AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
264
265	{AADDV, C_ADD0CON, C_REG, C_REG, 4, 4, 0, sys.MIPS64, 0},
266	{AADDV, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, sys.MIPS64, 0},
267	{AADDV, C_ANDCON, C_REG, C_REG, 10, 8, 0, sys.MIPS64, 0},
268	{AADDV, C_ANDCON, C_NONE, C_REG, 10, 8, 0, sys.MIPS64, 0},
269
270	{AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
271	{AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
272	{AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
273	{AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
274
275	{AADD, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
276	{AADD, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
277	{AADDV, C_UCON, C_REG, C_REG, 25, 8, 0, sys.MIPS64, 0},
278	{AADDV, C_UCON, C_NONE, C_REG, 25, 8, 0, sys.MIPS64, 0},
279	{AAND, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
280	{AAND, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
281
282	{AADD, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
283	{AADDV, C_LCON, C_NONE, C_REG, 23, 12, 0, sys.MIPS64, 0},
284	{AAND, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
285	{AADD, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
286	{AADDV, C_LCON, C_REG, C_REG, 23, 12, 0, sys.MIPS64, 0},
287	{AAND, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
288
289	{ASLL, C_SCON, C_REG, C_REG, 16, 4, 0, 0, 0},
290	{ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0, 0, 0},
291
292	{ASLLV, C_SCON, C_REG, C_REG, 16, 4, 0, sys.MIPS64, 0},
293	{ASLLV, C_SCON, C_NONE, C_REG, 16, 4, 0, sys.MIPS64, 0},
294
295	{ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
296
297	{ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0, 0, 0},
298	{ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
299	{ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
300	{ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0, 0, NOTUSETMP},
301
302	{AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
303	{AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
304
305	{AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO, 0, 0},
306	{AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK, 0, 0},
307
308	{AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
309	{AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
310	{AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
311	{AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, sys.MIPS64, 0},
312	{AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
313	{AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
314	{AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, sys.MIPS64, 0},
315	{AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
316	{AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
317
318	{AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
319	{AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
320	{AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
321	{AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, sys.MIPS64, 0},
322	{AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
323	{AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
324	{AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, sys.MIPS64, 0},
325	{AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
326	{AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
327	{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
328	{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
329	{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
330	{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
331
332	{AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
333	{AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
334	{AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
335	{AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, sys.MIPS64, 0},
336	{AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
337	{AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
338	{AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, sys.MIPS64, 0},
339	{AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
340	{AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
341
342	{AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
343	{AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
344	{AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
345	{AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, sys.MIPS64, 0},
346	{AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
347	{AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
348	{AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, sys.MIPS64, 0},
349	{AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
350	{AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
351	{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
352	{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
353	{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
354	{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
355
356	{AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0, 0, 0},
357	{AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0, 0, 0},
358	{AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0, sys.MIPS64, 0},
359	{AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0, sys.MIPS64, 0},
360
361	{AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
362	{AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
363
364	{AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0, 0, 0},
365	{AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0, sys.MIPS64, 0},
366	{AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0, 0, 0},
367	{AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0, sys.MIPS64, 0},
368
369	{AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0, 0},
370
371	{AMOVW, C_REG, C_NONE, C_FCREG, 41, 4, 0, 0, 0},
372	{AMOVV, C_REG, C_NONE, C_FCREG, 41, 4, 0, sys.MIPS64, 0},
373	{AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0, 0},
374	{AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, sys.MIPS64, 0},
375
376	{ATEQ, C_SCON, C_REG, C_REG, 15, 4, 0, 0, 0},
377	{ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
378	{ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
379
380	{AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
381	{AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
382	{AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
383	{AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
384
385	{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
386	{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
387	{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
388	{ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
389
390	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0},
391	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
392	{obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
393	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
394	{obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
395	{obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
396	{obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
397	{obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
398	{obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
399
400	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
401}
402
403var oprange [ALAST & obj.AMask][]Optab
404
405var xcmp [C_NCLASS][C_NCLASS]bool
406
407func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
408	if ctxt.Retpoline {
409		ctxt.Diag("-spectre=ret not supported on mips")
410		ctxt.Retpoline = false // don't keep printing
411	}
412
413	p := cursym.Func().Text
414	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
415		return
416	}
417
418	c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.FixedFrameSize())}
419
420	if oprange[AOR&obj.AMask] == nil {
421		c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
422	}
423
424	pc := int64(0)
425	p.Pc = pc
426
427	var m int
428	var o *Optab
429	for p = p.Link; p != nil; p = p.Link {
430		p.Pc = pc
431		o = c.oplook(p)
432		m = int(o.size)
433		if m == 0 {
434			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
435				c.ctxt.Diag("zero-width instruction\n%v", p)
436			}
437			continue
438		}
439
440		pc += int64(m)
441	}
442
443	c.cursym.Size = pc
444
445	/*
446	 * if any procedure is large enough to
447	 * generate a large SBRA branch, then
448	 * generate extra passes putting branches
449	 * around jmps to fix. this is rare.
450	 */
451	bflag := 1
452
453	var otxt int64
454	var q *obj.Prog
455	for bflag != 0 {
456		bflag = 0
457		pc = 0
458		for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
459			p.Pc = pc
460			o = c.oplook(p)
461
462			// very large conditional branches
463			if o.type_ == 6 && p.To.Target() != nil {
464				otxt = p.To.Target().Pc - pc
465				if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
466					q = c.newprog()
467					q.Link = p.Link
468					p.Link = q
469					q.As = AJMP
470					q.Pos = p.Pos
471					q.To.Type = obj.TYPE_BRANCH
472					q.To.SetTarget(p.To.Target())
473					p.To.SetTarget(q)
474					q = c.newprog()
475					q.Link = p.Link
476					p.Link = q
477					q.As = AJMP
478					q.Pos = p.Pos
479					q.To.Type = obj.TYPE_BRANCH
480					q.To.SetTarget(q.Link.Link)
481
482					c.addnop(p.Link)
483					c.addnop(p)
484					bflag = 1
485				}
486			}
487
488			m = int(o.size)
489			if m == 0 {
490				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
491					c.ctxt.Diag("zero-width instruction\n%v", p)
492				}
493				continue
494			}
495
496			pc += int64(m)
497		}
498
499		c.cursym.Size = pc
500	}
501	if c.ctxt.Arch.Family == sys.MIPS64 {
502		pc += -pc & (mips64FuncAlign - 1)
503	}
504	c.cursym.Size = pc
505
506	/*
507	 * lay out the code, emitting code and data relocations.
508	 */
509
510	c.cursym.Grow(c.cursym.Size)
511
512	bp := c.cursym.P
513	var i int32
514	var out [4]uint32
515	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
516		c.pc = p.Pc
517		o = c.oplook(p)
518		if int(o.size) > 4*len(out) {
519			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
520		}
521		c.asmout(p, o, out[:])
522		for i = 0; i < int32(o.size/4); i++ {
523			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
524			bp = bp[4:]
525		}
526	}
527
528	// Mark nonpreemptible instruction sequences.
529	// We use REGTMP as a scratch register during call injection,
530	// so instruction sequences that use REGTMP are unsafe to
531	// preempt asynchronously.
532	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
533}
534
535// isUnsafePoint returns whether p is an unsafe point.
536func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
537	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
538	// preemption sequence clobbers REGTMP.
539	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
540}
541
542// isRestartable returns whether p is a multi-instruction sequence that,
543// if preempted, can be restarted.
544func (c *ctxt0) isRestartable(p *obj.Prog) bool {
545	if c.isUnsafePoint(p) {
546		return false
547	}
548	// If p is a multi-instruction sequence with uses REGTMP inserted by
549	// the assembler in order to materialize a large constant/offset, we
550	// can restart p (at the start of the instruction sequence), recompute
551	// the content of REGTMP, upon async preemption. Currently, all cases
552	// of assembler-inserted REGTMP fall into this category.
553	// If p doesn't use REGTMP, it can be simply preempted, so we don't
554	// mark it.
555	o := c.oplook(p)
556	return o.size > 4 && o.flag&NOTUSETMP == 0
557}
558
559func isint32(v int64) bool {
560	return int64(int32(v)) == v
561}
562
563func isuint32(v uint64) bool {
564	return uint64(uint32(v)) == v
565}
566
567func (c *ctxt0) aclass(a *obj.Addr) int {
568	switch a.Type {
569	case obj.TYPE_NONE:
570		return C_NONE
571
572	case obj.TYPE_REG:
573		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
574			return C_REG
575		}
576		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
577			return C_FREG
578		}
579		if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
580			return C_MREG
581		}
582		if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
583			return C_FCREG
584		}
585		if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
586			return C_WREG
587		}
588		if a.Reg == REG_LO {
589			return C_LO
590		}
591		if a.Reg == REG_HI {
592			return C_HI
593		}
594		return C_GOK
595
596	case obj.TYPE_MEM:
597		switch a.Name {
598		case obj.NAME_EXTERN,
599			obj.NAME_STATIC:
600			if a.Sym == nil {
601				break
602			}
603			c.instoffset = a.Offset
604			if a.Sym != nil { // use relocation
605				if a.Sym.Type == objabi.STLSBSS {
606					return C_TLS
607				}
608				return C_ADDR
609			}
610			return C_LEXT
611
612		case obj.NAME_AUTO:
613			if a.Reg == REGSP {
614				// unset base register for better printing, since
615				// a.Offset is still relative to pseudo-SP.
616				a.Reg = obj.REG_NONE
617			}
618			c.instoffset = int64(c.autosize) + a.Offset
619			if c.instoffset >= -BIG && c.instoffset < BIG {
620				return C_SAUTO
621			}
622			return C_LAUTO
623
624		case obj.NAME_PARAM:
625			if a.Reg == REGSP {
626				// unset base register for better printing, since
627				// a.Offset is still relative to pseudo-FP.
628				a.Reg = obj.REG_NONE
629			}
630			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
631			if c.instoffset >= -BIG && c.instoffset < BIG {
632				return C_SAUTO
633			}
634			return C_LAUTO
635
636		case obj.NAME_NONE:
637			c.instoffset = a.Offset
638			if c.instoffset == 0 {
639				return C_ZOREG
640			}
641			if c.instoffset >= -BIG && c.instoffset < BIG {
642				return C_SOREG
643			}
644			return C_LOREG
645		}
646
647		return C_GOK
648
649	case obj.TYPE_TEXTSIZE:
650		return C_TEXTSIZE
651
652	case obj.TYPE_CONST,
653		obj.TYPE_ADDR:
654		switch a.Name {
655		case obj.NAME_NONE:
656			c.instoffset = a.Offset
657			if a.Reg != 0 {
658				if -BIG <= c.instoffset && c.instoffset <= BIG {
659					return C_SACON
660				}
661				if isint32(c.instoffset) {
662					return C_LACON
663				}
664				return C_DACON
665			}
666
667		case obj.NAME_EXTERN,
668			obj.NAME_STATIC:
669			s := a.Sym
670			if s == nil {
671				return C_GOK
672			}
673
674			c.instoffset = a.Offset
675			if s.Type == objabi.STLSBSS {
676				return C_STCON // address of TLS variable
677			}
678			return C_LECON
679
680		case obj.NAME_AUTO:
681			if a.Reg == REGSP {
682				// unset base register for better printing, since
683				// a.Offset is still relative to pseudo-SP.
684				a.Reg = obj.REG_NONE
685			}
686			c.instoffset = int64(c.autosize) + a.Offset
687			if c.instoffset >= -BIG && c.instoffset < BIG {
688				return C_SACON
689			}
690			return C_LACON
691
692		case obj.NAME_PARAM:
693			if a.Reg == REGSP {
694				// unset base register for better printing, since
695				// a.Offset is still relative to pseudo-FP.
696				a.Reg = obj.REG_NONE
697			}
698			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
699			if c.instoffset >= -BIG && c.instoffset < BIG {
700				return C_SACON
701			}
702			return C_LACON
703
704		default:
705			return C_GOK
706		}
707
708		if c.instoffset >= 0 {
709			if c.instoffset == 0 {
710				return C_ZCON
711			}
712			if c.instoffset <= 0x7fff {
713				return C_SCON
714			}
715			if c.instoffset <= 0xffff {
716				return C_ANDCON
717			}
718			if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
719				return C_UCON
720			}
721			if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
722				return C_LCON
723			}
724			return C_LCON // C_DCON
725		}
726
727		if c.instoffset >= -0x8000 {
728			return C_ADDCON
729		}
730		if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
731			return C_UCON
732		}
733		if isint32(c.instoffset) {
734			return C_LCON
735		}
736		return C_LCON // C_DCON
737
738	case obj.TYPE_BRANCH:
739		return C_SBRA
740	}
741
742	return C_GOK
743}
744
745func prasm(p *obj.Prog) {
746	fmt.Printf("%v\n", p)
747}
748
749func (c *ctxt0) oplook(p *obj.Prog) *Optab {
750	if oprange[AOR&obj.AMask] == nil {
751		c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
752	}
753
754	a1 := int(p.Optab)
755	if a1 != 0 {
756		return &optab[a1-1]
757	}
758	a1 = int(p.From.Class)
759	if a1 == 0 {
760		a1 = c.aclass(&p.From) + 1
761		p.From.Class = int8(a1)
762	}
763
764	a1--
765	a3 := int(p.To.Class)
766	if a3 == 0 {
767		a3 = c.aclass(&p.To) + 1
768		p.To.Class = int8(a3)
769	}
770
771	a3--
772	a2 := C_NONE
773	if p.Reg != 0 {
774		a2 = C_REG
775	}
776
777	ops := oprange[p.As&obj.AMask]
778	c1 := &xcmp[a1]
779	c3 := &xcmp[a3]
780	for i := range ops {
781		op := &ops[i]
782		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && (op.family == 0 || c.ctxt.Arch.Family == op.family) {
783			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
784			return op
785		}
786	}
787
788	c.ctxt.Diag("illegal combination %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
789	prasm(p)
790	// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
791	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0}
792}
793
794func cmp(a int, b int) bool {
795	if a == b {
796		return true
797	}
798	switch a {
799	case C_LCON:
800		if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
801			return true
802		}
803
804	case C_ADD0CON:
805		if b == C_ADDCON {
806			return true
807		}
808		fallthrough
809
810	case C_ADDCON:
811		if b == C_ZCON || b == C_SCON {
812			return true
813		}
814
815	case C_AND0CON:
816		if b == C_ANDCON {
817			return true
818		}
819		fallthrough
820
821	case C_ANDCON:
822		if b == C_ZCON || b == C_SCON {
823			return true
824		}
825
826	case C_UCON:
827		if b == C_ZCON {
828			return true
829		}
830
831	case C_SCON:
832		if b == C_ZCON {
833			return true
834		}
835
836	case C_LACON:
837		if b == C_SACON {
838			return true
839		}
840
841	case C_LBRA:
842		if b == C_SBRA {
843			return true
844		}
845
846	case C_LEXT:
847		if b == C_SEXT {
848			return true
849		}
850
851	case C_LAUTO:
852		if b == C_SAUTO {
853			return true
854		}
855
856	case C_REG:
857		if b == C_ZCON {
858			return r0iszero != 0 /*TypeKind(100016)*/
859		}
860
861	case C_LOREG:
862		if b == C_ZOREG || b == C_SOREG {
863			return true
864		}
865
866	case C_SOREG:
867		if b == C_ZOREG {
868			return true
869		}
870	}
871
872	return false
873}
874
875type ocmp []Optab
876
877func (x ocmp) Len() int {
878	return len(x)
879}
880
881func (x ocmp) Swap(i, j int) {
882	x[i], x[j] = x[j], x[i]
883}
884
885func (x ocmp) Less(i, j int) bool {
886	p1 := &x[i]
887	p2 := &x[j]
888	n := int(p1.as) - int(p2.as)
889	if n != 0 {
890		return n < 0
891	}
892	n = int(p1.a1) - int(p2.a1)
893	if n != 0 {
894		return n < 0
895	}
896	n = int(p1.a2) - int(p2.a2)
897	if n != 0 {
898		return n < 0
899	}
900	n = int(p1.a3) - int(p2.a3)
901	if n != 0 {
902		return n < 0
903	}
904	return false
905}
906
907func opset(a, b0 obj.As) {
908	oprange[a&obj.AMask] = oprange[b0]
909}
910
911func buildop(ctxt *obj.Link) {
912	if oprange[AOR&obj.AMask] != nil {
913		// Already initialized; stop now.
914		// This happens in the cmd/asm tests,
915		// each of which re-initializes the arch.
916		return
917	}
918
919	var n int
920
921	for i := 0; i < C_NCLASS; i++ {
922		for n = 0; n < C_NCLASS; n++ {
923			if cmp(n, i) {
924				xcmp[i][n] = true
925			}
926		}
927	}
928	for n = 0; optab[n].as != obj.AXXX; n++ {
929	}
930	sort.Sort(ocmp(optab[:n]))
931	for i := 0; i < n; i++ {
932		r := optab[i].as
933		r0 := r & obj.AMask
934		start := i
935		for optab[i].as == r {
936			i++
937		}
938		oprange[r0] = optab[start:i]
939		i--
940
941		switch r {
942		default:
943			ctxt.Diag("unknown op in build: %v", r)
944			ctxt.DiagFlush()
945			log.Fatalf("bad code")
946
947		case AABSF:
948			opset(AMOVFD, r0)
949			opset(AMOVDF, r0)
950			opset(AMOVWF, r0)
951			opset(AMOVFW, r0)
952			opset(AMOVWD, r0)
953			opset(AMOVDW, r0)
954			opset(ANEGF, r0)
955			opset(ANEGD, r0)
956			opset(AABSD, r0)
957			opset(ATRUNCDW, r0)
958			opset(ATRUNCFW, r0)
959			opset(ASQRTF, r0)
960			opset(ASQRTD, r0)
961
962		case AMOVVF:
963			opset(AMOVVD, r0)
964			opset(AMOVFV, r0)
965			opset(AMOVDV, r0)
966			opset(ATRUNCDV, r0)
967			opset(ATRUNCFV, r0)
968
969		case AADD:
970			opset(ASGT, r0)
971			opset(ASGTU, r0)
972			opset(AADDU, r0)
973
974		case AADDV:
975			opset(AADDVU, r0)
976
977		case AADDF:
978			opset(ADIVF, r0)
979			opset(ADIVD, r0)
980			opset(AMULF, r0)
981			opset(AMULD, r0)
982			opset(ASUBF, r0)
983			opset(ASUBD, r0)
984			opset(AADDD, r0)
985
986		case AAND:
987			opset(AOR, r0)
988			opset(AXOR, r0)
989
990		case ABEQ:
991			opset(ABNE, r0)
992
993		case ABLEZ:
994			opset(ABGEZ, r0)
995			opset(ABGEZAL, r0)
996			opset(ABLTZ, r0)
997			opset(ABLTZAL, r0)
998			opset(ABGTZ, r0)
999
1000		case AMOVB:
1001			opset(AMOVH, r0)
1002
1003		case AMOVBU:
1004			opset(AMOVHU, r0)
1005
1006		case AMUL:
1007			opset(AREM, r0)
1008			opset(AREMU, r0)
1009			opset(ADIVU, r0)
1010			opset(AMULU, r0)
1011			opset(ADIV, r0)
1012			opset(AMADD, r0)
1013			opset(AMSUB, r0)
1014
1015		case AMULV:
1016			opset(ADIVV, r0)
1017			opset(ADIVVU, r0)
1018			opset(AMULVU, r0)
1019			opset(AREMV, r0)
1020			opset(AREMVU, r0)
1021
1022		case ASLL:
1023			opset(ASRL, r0)
1024			opset(ASRA, r0)
1025			opset(AROTR, r0)
1026
1027		case ASLLV:
1028			opset(ASRAV, r0)
1029			opset(ASRLV, r0)
1030			opset(AROTRV, r0)
1031
1032		case ASUB:
1033			opset(ASUBU, r0)
1034			opset(ANOR, r0)
1035
1036		case ASUBV:
1037			opset(ASUBVU, r0)
1038
1039		case ASYSCALL:
1040			opset(ASYNC, r0)
1041			opset(ANOOP, r0)
1042			opset(ATLBP, r0)
1043			opset(ATLBR, r0)
1044			opset(ATLBWI, r0)
1045			opset(ATLBWR, r0)
1046
1047		case ACMPEQF:
1048			opset(ACMPGTF, r0)
1049			opset(ACMPGTD, r0)
1050			opset(ACMPGEF, r0)
1051			opset(ACMPGED, r0)
1052			opset(ACMPEQD, r0)
1053
1054		case ABFPT:
1055			opset(ABFPF, r0)
1056
1057		case AMOVWL:
1058			opset(AMOVWR, r0)
1059
1060		case AMOVVL:
1061			opset(AMOVVR, r0)
1062
1063		case AVMOVB:
1064			opset(AVMOVH, r0)
1065			opset(AVMOVW, r0)
1066			opset(AVMOVD, r0)
1067
1068		case AMOVW,
1069			AMOVD,
1070			AMOVF,
1071			AMOVV,
1072			ABREAK,
1073			ARFE,
1074			AJAL,
1075			AJMP,
1076			AMOVWU,
1077			ALL,
1078			ALLV,
1079			ASC,
1080			ASCV,
1081			ANEGW,
1082			ANEGV,
1083			AWORD,
1084			obj.ANOP,
1085			obj.ATEXT,
1086			obj.AUNDEF,
1087			obj.AFUNCDATA,
1088			obj.APCDATA,
1089			obj.ADUFFZERO,
1090			obj.ADUFFCOPY:
1091			break
1092
1093		case ACMOVN:
1094			opset(ACMOVZ, r0)
1095
1096		case ACMOVT:
1097			opset(ACMOVF, r0)
1098
1099		case ACLO:
1100			opset(ACLZ, r0)
1101
1102		case ATEQ:
1103			opset(ATNE, r0)
1104		}
1105	}
1106}
1107
1108func OP(x uint32, y uint32) uint32 {
1109	return x<<3 | y<<0
1110}
1111
1112func SP(x uint32, y uint32) uint32 {
1113	return x<<29 | y<<26
1114}
1115
1116func BCOND(x uint32, y uint32) uint32 {
1117	return x<<19 | y<<16
1118}
1119
1120func MMU(x uint32, y uint32) uint32 {
1121	return SP(2, 0) | 16<<21 | x<<3 | y<<0
1122}
1123
1124func FPF(x uint32, y uint32) uint32 {
1125	return SP(2, 1) | 16<<21 | x<<3 | y<<0
1126}
1127
1128func FPD(x uint32, y uint32) uint32 {
1129	return SP(2, 1) | 17<<21 | x<<3 | y<<0
1130}
1131
1132func FPW(x uint32, y uint32) uint32 {
1133	return SP(2, 1) | 20<<21 | x<<3 | y<<0
1134}
1135
1136func FPV(x uint32, y uint32) uint32 {
1137	return SP(2, 1) | 21<<21 | x<<3 | y<<0
1138}
1139
1140func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1141	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
1142}
1143
1144func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
1145	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
1146}
1147
1148func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
1149	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
1150}
1151
1152func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1153	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
1154}
1155
1156func OP_JMP(op uint32, i uint32) uint32 {
1157	return op | i&0x3FFFFFF
1158}
1159
1160func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
1161	return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
1162}
1163
1164func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
1165	return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
1166}
1167
1168func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1169	o1 := uint32(0)
1170	o2 := uint32(0)
1171	o3 := uint32(0)
1172	o4 := uint32(0)
1173
1174	add := AADDU
1175
1176	if c.ctxt.Arch.Family == sys.MIPS64 {
1177		add = AADDVU
1178	}
1179	switch o.type_ {
1180	default:
1181		c.ctxt.Diag("unknown type %d %v", o.type_)
1182		prasm(p)
1183
1184	case 0: /* pseudo ops */
1185		break
1186
1187	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
1188		a := AOR
1189		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
1190			// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
1191			// but SLL is special that the result is always sign-extended to 64-bit.
1192			a = ASLL
1193		}
1194		o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
1195
1196	case 2: /* add/sub r1,[r2],r3 */
1197		r := int(p.Reg)
1198		if p.As == ANEGW || p.As == ANEGV {
1199			r = REGZERO
1200		}
1201		if r == 0 {
1202			r = int(p.To.Reg)
1203		}
1204		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1205
1206	case 3: /* mov $soreg, r ==> or/add $i,o,r */
1207		v := c.regoff(&p.From)
1208
1209		r := int(p.From.Reg)
1210		if r == 0 {
1211			r = int(o.param)
1212		}
1213		a := add
1214		if o.a1 == C_ANDCON {
1215			a = AOR
1216		}
1217
1218		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1219
1220	case 4: /* add $scon,[r1],r2 */
1221		v := c.regoff(&p.From)
1222
1223		r := int(p.Reg)
1224		if r == 0 {
1225			r = int(p.To.Reg)
1226		}
1227
1228		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1229
1230	case 5: /* syscall */
1231		o1 = c.oprrr(p.As)
1232
1233	case 6: /* beq r1,[r2],sbra */
1234		v := int32(0)
1235		if p.To.Target() == nil {
1236			v = int32(-4) >> 2
1237		} else {
1238			v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1239		}
1240		if (v<<16)>>16 != v {
1241			c.ctxt.Diag("short branch too far\n%v", p)
1242		}
1243		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
1244		// for ABFPT and ABFPF only: always fill delay slot with 0
1245		// see comments in func preprocess for details.
1246		o2 = 0
1247
1248	case 7: /* mov r, soreg ==> sw o(r) */
1249		r := int(p.To.Reg)
1250		if r == 0 {
1251			r = int(o.param)
1252		}
1253		v := c.regoff(&p.To)
1254		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1255
1256	case 8: /* mov soreg, r ==> lw o(r) */
1257		r := int(p.From.Reg)
1258		if r == 0 {
1259			r = int(o.param)
1260		}
1261		v := c.regoff(&p.From)
1262		o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1263
1264	case 9: /* sll r1,[r2],r3 */
1265		r := int(p.Reg)
1266
1267		if r == 0 {
1268			r = int(p.To.Reg)
1269		}
1270		o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
1271
1272	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
1273		v := c.regoff(&p.From)
1274		a := AOR
1275		if v < 0 {
1276			a = AADDU
1277		}
1278		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1279		r := int(p.Reg)
1280		if r == 0 {
1281			r = int(p.To.Reg)
1282		}
1283		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1284
1285	case 11: /* jmp lbra */
1286		v := int32(0)
1287		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
1288			// use PC-relative branch for short branches
1289			// BEQ	R0, R0, sbra
1290			if p.To.Target() == nil {
1291				v = int32(-4) >> 2
1292			} else {
1293				v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1294			}
1295			if (v<<16)>>16 == v {
1296				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
1297				break
1298			}
1299		}
1300		if p.To.Target() == nil {
1301			v = int32(p.Pc) >> 2
1302		} else {
1303			v = int32(p.To.Target().Pc) >> 2
1304		}
1305		o1 = OP_JMP(c.opirr(p.As), uint32(v))
1306		if p.To.Sym == nil {
1307			p.To.Sym = c.cursym.Func().Text.From.Sym
1308			p.To.Offset = p.To.Target().Pc
1309		}
1310		rel := obj.Addrel(c.cursym)
1311		rel.Off = int32(c.pc)
1312		rel.Siz = 4
1313		rel.Sym = p.To.Sym
1314		rel.Add = p.To.Offset
1315		if p.As == AJAL {
1316			rel.Type = objabi.R_CALLMIPS
1317		} else {
1318			rel.Type = objabi.R_JMPMIPS
1319		}
1320
1321	case 12: /* movbs r,r */
1322		// NOTE: this case does not use REGTMP. If it ever does,
1323		// remove the NOTUSETMP flag in optab.
1324		v := 16
1325		if p.As == AMOVB {
1326			v = 24
1327		}
1328		o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
1329		o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1330
1331	case 13: /* movbu r,r */
1332		if p.As == AMOVBU {
1333			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1334		} else {
1335			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
1336		}
1337
1338	case 14: /* movwu r,r */
1339		// NOTE: this case does not use REGTMP. If it ever does,
1340		// remove the NOTUSETMP flag in optab.
1341		o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1342		o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1343
1344	case 15: /* teq $c r,r */
1345		v := c.regoff(&p.From)
1346		r := int(p.Reg)
1347		if r == 0 {
1348			r = REGZERO
1349		}
1350		/* only use 10 bits of trap code */
1351		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
1352
1353	case 16: /* sll $c,[r1],r2 */
1354		v := c.regoff(&p.From)
1355		r := int(p.Reg)
1356		if r == 0 {
1357			r = int(p.To.Reg)
1358		}
1359
1360		/* OP_SRR will use only the low 5 bits of the shift value */
1361		if v >= 32 && vshift(p.As) {
1362			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
1363		} else {
1364			o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1365		}
1366
1367	case 17:
1368		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
1369
1370	case 18: /* jmp [r1],0(r2) */
1371		r := int(p.Reg)
1372		if r == 0 {
1373			r = int(o.param)
1374		}
1375		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
1376		if p.As == obj.ACALL {
1377			rel := obj.Addrel(c.cursym)
1378			rel.Off = int32(c.pc)
1379			rel.Siz = 0
1380			rel.Type = objabi.R_CALLIND
1381		}
1382
1383	case 19: /* mov $lcon,r ==> lu+or */
1384		// NOTE: this case does not use REGTMP. If it ever does,
1385		// remove the NOTUSETMP flag in optab.
1386		v := c.regoff(&p.From)
1387		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1388		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1389
1390	case 20: /* mov lo/hi,r */
1391		a := OP(2, 0) /* mfhi */
1392		if p.From.Reg == REG_LO {
1393			a = OP(2, 2) /* mflo */
1394		}
1395		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
1396
1397	case 21: /* mov r,lo/hi */
1398		a := OP(2, 1) /* mthi */
1399		if p.To.Reg == REG_LO {
1400			a = OP(2, 3) /* mtlo */
1401		}
1402		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
1403
1404	case 22: /* mul r1,r2 [r3]*/
1405		if p.To.Reg != 0 {
1406			r := int(p.Reg)
1407			if r == 0 {
1408				r = int(p.To.Reg)
1409			}
1410			a := SP(3, 4) | 2 /* mul */
1411			o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1412		} else {
1413			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
1414		}
1415
1416	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
1417		v := c.regoff(&p.From)
1418		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1419		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1420		r := int(p.Reg)
1421		if r == 0 {
1422			r = int(p.To.Reg)
1423		}
1424		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1425
1426	case 24: /* mov $ucon,r ==> lu r */
1427		v := c.regoff(&p.From)
1428		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1429
1430	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
1431		v := c.regoff(&p.From)
1432		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1433		r := int(p.Reg)
1434		if r == 0 {
1435			r = int(p.To.Reg)
1436		}
1437		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1438
1439	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
1440		v := c.regoff(&p.From)
1441		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1442		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1443		r := int(p.From.Reg)
1444		if r == 0 {
1445			r = int(o.param)
1446		}
1447		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1448
1449	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1450		v := c.regoff(&p.From)
1451		r := int(p.From.Reg)
1452		if r == 0 {
1453			r = int(o.param)
1454		}
1455		a := -AMOVF
1456		if p.As == AMOVD {
1457			a = -AMOVD
1458		}
1459		switch o.size {
1460		case 12:
1461			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1462			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1463			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1464
1465		case 4:
1466			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1467		}
1468
1469	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1470		v := c.regoff(&p.To)
1471		r := int(p.To.Reg)
1472		if r == 0 {
1473			r = int(o.param)
1474		}
1475		a := AMOVF
1476		if p.As == AMOVD {
1477			a = AMOVD
1478		}
1479		switch o.size {
1480		case 12:
1481			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1482			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1483			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1484
1485		case 4:
1486			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
1487		}
1488
1489	case 30: /* movw r,fr */
1490		a := SP(2, 1) | (4 << 21) /* mtc1 */
1491		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1492
1493	case 31: /* movw fr,r */
1494		a := SP(2, 1) | (0 << 21) /* mtc1 */
1495		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1496
1497	case 32: /* fadd fr1,[fr2],fr3 */
1498		r := int(p.Reg)
1499		if r == 0 {
1500			r = int(p.To.Reg)
1501		}
1502		o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1503
1504	case 33: /* fabs fr1, fr3 */
1505		o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1506
1507	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
1508		v := c.regoff(&p.From)
1509		a := AADDU
1510		if o.a1 == C_ANDCON {
1511			a = AOR
1512		}
1513		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1514		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
1515
1516	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
1517		v := c.regoff(&p.To)
1518		r := int(p.To.Reg)
1519		if r == 0 {
1520			r = int(o.param)
1521		}
1522		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1523		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1524		o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1525
1526	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
1527		v := c.regoff(&p.From)
1528		r := int(p.From.Reg)
1529		if r == 0 {
1530			r = int(o.param)
1531		}
1532		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1533		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1534		o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1535
1536	case 37: /* movw r,mr */
1537		a := SP(2, 0) | (4 << 21) /* mtc0 */
1538		if p.As == AMOVV {
1539			a = SP(2, 0) | (5 << 21) /* dmtc0 */
1540		}
1541		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1542
1543	case 38: /* movw mr,r */
1544		a := SP(2, 0) | (0 << 21) /* mfc0 */
1545		if p.As == AMOVV {
1546			a = SP(2, 0) | (1 << 21) /* dmfc0 */
1547		}
1548		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1549
1550	case 40: /* word */
1551		o1 = uint32(c.regoff(&p.From))
1552
1553	case 41: /* movw f,fcr */
1554		o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
1555
1556	case 42: /* movw fcr,r */
1557		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
1558
1559	case 47: /* movv r,fr */
1560		a := SP(2, 1) | (5 << 21) /* dmtc1 */
1561		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1562
1563	case 48: /* movv fr,r */
1564		a := SP(2, 1) | (1 << 21) /* dmtc1 */
1565		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1566
1567	case 49: /* undef */
1568		o1 = 52 /* trap -- teq r0, r0 */
1569
1570	/* relocation operations */
1571	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
1572		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1573		rel := obj.Addrel(c.cursym)
1574		rel.Off = int32(c.pc)
1575		rel.Siz = 4
1576		rel.Sym = p.To.Sym
1577		rel.Add = p.To.Offset
1578		rel.Type = objabi.R_ADDRMIPSU
1579		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1580		rel2 := obj.Addrel(c.cursym)
1581		rel2.Off = int32(c.pc + 4)
1582		rel2.Siz = 4
1583		rel2.Sym = p.To.Sym
1584		rel2.Add = p.To.Offset
1585		rel2.Type = objabi.R_ADDRMIPS
1586
1587		if o.size == 12 {
1588			o3 = o2
1589			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1590			rel2.Off += 4
1591		}
1592
1593	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
1594		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1595		rel := obj.Addrel(c.cursym)
1596		rel.Off = int32(c.pc)
1597		rel.Siz = 4
1598		rel.Sym = p.From.Sym
1599		rel.Add = p.From.Offset
1600		rel.Type = objabi.R_ADDRMIPSU
1601		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1602		rel2 := obj.Addrel(c.cursym)
1603		rel2.Off = int32(c.pc + 4)
1604		rel2.Siz = 4
1605		rel2.Sym = p.From.Sym
1606		rel2.Add = p.From.Offset
1607		rel2.Type = objabi.R_ADDRMIPS
1608
1609		if o.size == 12 {
1610			o3 = o2
1611			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1612			rel2.Off += 4
1613		}
1614
1615	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
1616		// NOTE: this case does not use REGTMP. If it ever does,
1617		// remove the NOTUSETMP flag in optab.
1618		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
1619		rel := obj.Addrel(c.cursym)
1620		rel.Off = int32(c.pc)
1621		rel.Siz = 4
1622		rel.Sym = p.From.Sym
1623		rel.Add = p.From.Offset
1624		rel.Type = objabi.R_ADDRMIPSU
1625		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1626		rel2 := obj.Addrel(c.cursym)
1627		rel2.Off = int32(c.pc + 4)
1628		rel2.Siz = 4
1629		rel2.Sym = p.From.Sym
1630		rel2.Add = p.From.Offset
1631		rel2.Type = objabi.R_ADDRMIPS
1632
1633		if o.size == 12 {
1634			o3 = o2
1635			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
1636			rel2.Off += 4
1637		}
1638
1639	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1640		// clobbers R3 !
1641		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
1642		// NOTE: this case does not use REGTMP. If it ever does,
1643		// remove the NOTUSETMP flag in optab.
1644		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1645		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
1646		rel := obj.Addrel(c.cursym)
1647		rel.Off = int32(c.pc + 4)
1648		rel.Siz = 4
1649		rel.Sym = p.To.Sym
1650		rel.Add = p.To.Offset
1651		rel.Type = objabi.R_ADDRMIPSTLS
1652
1653	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1654		// clobbers R3 !
1655		// NOTE: this case does not use REGTMP. If it ever does,
1656		// remove the NOTUSETMP flag in optab.
1657		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1658		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1659		rel := obj.Addrel(c.cursym)
1660		rel.Off = int32(c.pc + 4)
1661		rel.Siz = 4
1662		rel.Sym = p.From.Sym
1663		rel.Add = p.From.Offset
1664		rel.Type = objabi.R_ADDRMIPSTLS
1665
1666	case 55: /* mov $tlsvar, r ==> rdhwr + add */
1667		// clobbers R3 !
1668		// NOTE: this case does not use REGTMP. If it ever does,
1669		// remove the NOTUSETMP flag in optab.
1670		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1671		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1672		rel := obj.Addrel(c.cursym)
1673		rel.Off = int32(c.pc + 4)
1674		rel.Siz = 4
1675		rel.Sym = p.From.Sym
1676		rel.Add = p.From.Offset
1677		rel.Type = objabi.R_ADDRMIPSTLS
1678
1679	case 56: /* vmov{b,h,w,d} $scon, wr */
1680
1681		v := c.regoff(&p.From)
1682		o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
1683
1684	case 57: /* vld $soreg, wr */
1685		v := c.lsoffset(p.As, c.regoff(&p.From))
1686		o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
1687
1688	case 58: /* vst wr, $soreg */
1689		v := c.lsoffset(p.As, c.regoff(&p.To))
1690		o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
1691	}
1692
1693	out[0] = o1
1694	out[1] = o2
1695	out[2] = o3
1696	out[3] = o4
1697}
1698
1699func (c *ctxt0) vregoff(a *obj.Addr) int64 {
1700	c.instoffset = 0
1701	c.aclass(a)
1702	return c.instoffset
1703}
1704
1705func (c *ctxt0) regoff(a *obj.Addr) int32 {
1706	return int32(c.vregoff(a))
1707}
1708
1709func (c *ctxt0) oprrr(a obj.As) uint32 {
1710	switch a {
1711	case AADD:
1712		return OP(4, 0)
1713	case AADDU:
1714		return OP(4, 1)
1715	case ASGT:
1716		return OP(5, 2)
1717	case ASGTU:
1718		return OP(5, 3)
1719	case AAND:
1720		return OP(4, 4)
1721	case AOR:
1722		return OP(4, 5)
1723	case AXOR:
1724		return OP(4, 6)
1725	case ASUB:
1726		return OP(4, 2)
1727	case ASUBU, ANEGW:
1728		return OP(4, 3)
1729	case ANOR:
1730		return OP(4, 7)
1731	case ASLL:
1732		return OP(0, 4)
1733	case ASRL:
1734		return OP(0, 6)
1735	case ASRA:
1736		return OP(0, 7)
1737	case AROTR:
1738		return OP(8, 6)
1739	case ASLLV:
1740		return OP(2, 4)
1741	case ASRLV:
1742		return OP(2, 6)
1743	case ASRAV:
1744		return OP(2, 7)
1745	case AROTRV:
1746		return OP(10, 6)
1747	case AADDV:
1748		return OP(5, 4)
1749	case AADDVU:
1750		return OP(5, 5)
1751	case ASUBV:
1752		return OP(5, 6)
1753	case ASUBVU, ANEGV:
1754		return OP(5, 7)
1755	case AREM,
1756		ADIV:
1757		return OP(3, 2)
1758	case AREMU,
1759		ADIVU:
1760		return OP(3, 3)
1761	case AMUL:
1762		return OP(3, 0)
1763	case AMULU:
1764		return OP(3, 1)
1765	case AREMV,
1766		ADIVV:
1767		return OP(3, 6)
1768	case AREMVU,
1769		ADIVVU:
1770		return OP(3, 7)
1771	case AMULV:
1772		return OP(3, 4)
1773	case AMULVU:
1774		return OP(3, 5)
1775
1776	case AJMP:
1777		return OP(1, 0)
1778	case AJAL:
1779		return OP(1, 1)
1780
1781	case ABREAK:
1782		return OP(1, 5)
1783	case ASYSCALL:
1784		return OP(1, 4)
1785	case ATLBP:
1786		return MMU(1, 0)
1787	case ATLBR:
1788		return MMU(0, 1)
1789	case ATLBWI:
1790		return MMU(0, 2)
1791	case ATLBWR:
1792		return MMU(0, 6)
1793	case ARFE:
1794		return MMU(2, 0)
1795
1796	case ADIVF:
1797		return FPF(0, 3)
1798	case ADIVD:
1799		return FPD(0, 3)
1800	case AMULF:
1801		return FPF(0, 2)
1802	case AMULD:
1803		return FPD(0, 2)
1804	case ASUBF:
1805		return FPF(0, 1)
1806	case ASUBD:
1807		return FPD(0, 1)
1808	case AADDF:
1809		return FPF(0, 0)
1810	case AADDD:
1811		return FPD(0, 0)
1812	case ATRUNCFV:
1813		return FPF(1, 1)
1814	case ATRUNCDV:
1815		return FPD(1, 1)
1816	case ATRUNCFW:
1817		return FPF(1, 5)
1818	case ATRUNCDW:
1819		return FPD(1, 5)
1820	case AMOVFV:
1821		return FPF(4, 5)
1822	case AMOVDV:
1823		return FPD(4, 5)
1824	case AMOVVF:
1825		return FPV(4, 0)
1826	case AMOVVD:
1827		return FPV(4, 1)
1828	case AMOVFW:
1829		return FPF(4, 4)
1830	case AMOVDW:
1831		return FPD(4, 4)
1832	case AMOVWF:
1833		return FPW(4, 0)
1834	case AMOVDF:
1835		return FPD(4, 0)
1836	case AMOVWD:
1837		return FPW(4, 1)
1838	case AMOVFD:
1839		return FPF(4, 1)
1840	case AABSF:
1841		return FPF(0, 5)
1842	case AABSD:
1843		return FPD(0, 5)
1844	case AMOVF:
1845		return FPF(0, 6)
1846	case AMOVD:
1847		return FPD(0, 6)
1848	case ANEGF:
1849		return FPF(0, 7)
1850	case ANEGD:
1851		return FPD(0, 7)
1852	case ACMPEQF:
1853		return FPF(6, 2)
1854	case ACMPEQD:
1855		return FPD(6, 2)
1856	case ACMPGTF:
1857		return FPF(7, 4)
1858	case ACMPGTD:
1859		return FPD(7, 4)
1860	case ACMPGEF:
1861		return FPF(7, 6)
1862	case ACMPGED:
1863		return FPD(7, 6)
1864
1865	case ASQRTF:
1866		return FPF(0, 4)
1867	case ASQRTD:
1868		return FPD(0, 4)
1869
1870	case ASYNC:
1871		return OP(1, 7)
1872	case ANOOP:
1873		return 0
1874
1875	case ACMOVN:
1876		return OP(1, 3)
1877	case ACMOVZ:
1878		return OP(1, 2)
1879	case ACMOVT:
1880		return OP(0, 1) | (1 << 16)
1881	case ACMOVF:
1882		return OP(0, 1) | (0 << 16)
1883	case ACLO:
1884		return SP(3, 4) | OP(4, 1)
1885	case ACLZ:
1886		return SP(3, 4) | OP(4, 0)
1887	case AMADD:
1888		return SP(3, 4) | OP(0, 0)
1889	case AMSUB:
1890		return SP(3, 4) | OP(0, 4)
1891	}
1892
1893	if a < 0 {
1894		c.ctxt.Diag("bad rrr opcode -%v", -a)
1895	} else {
1896		c.ctxt.Diag("bad rrr opcode %v", a)
1897	}
1898	return 0
1899}
1900
1901func (c *ctxt0) opirr(a obj.As) uint32 {
1902	switch a {
1903	case AADD:
1904		return SP(1, 0)
1905	case AADDU:
1906		return SP(1, 1)
1907	case ASGT:
1908		return SP(1, 2)
1909	case ASGTU:
1910		return SP(1, 3)
1911	case AAND:
1912		return SP(1, 4)
1913	case AOR:
1914		return SP(1, 5)
1915	case AXOR:
1916		return SP(1, 6)
1917	case ALUI:
1918		return SP(1, 7)
1919	case ASLL:
1920		return OP(0, 0)
1921	case ASRL:
1922		return OP(0, 2)
1923	case ASRA:
1924		return OP(0, 3)
1925	case AROTR:
1926		return OP(0, 2) | 1<<21
1927	case AADDV:
1928		return SP(3, 0)
1929	case AADDVU:
1930		return SP(3, 1)
1931
1932	case AJMP:
1933		return SP(0, 2)
1934	case AJAL,
1935		obj.ADUFFZERO,
1936		obj.ADUFFCOPY:
1937		return SP(0, 3)
1938	case ABEQ:
1939		return SP(0, 4)
1940	case -ABEQ:
1941		return SP(2, 4) /* likely */
1942	case ABNE:
1943		return SP(0, 5)
1944	case -ABNE:
1945		return SP(2, 5) /* likely */
1946	case ABGEZ:
1947		return SP(0, 1) | BCOND(0, 1)
1948	case -ABGEZ:
1949		return SP(0, 1) | BCOND(0, 3) /* likely */
1950	case ABGEZAL:
1951		return SP(0, 1) | BCOND(2, 1)
1952	case -ABGEZAL:
1953		return SP(0, 1) | BCOND(2, 3) /* likely */
1954	case ABGTZ:
1955		return SP(0, 7)
1956	case -ABGTZ:
1957		return SP(2, 7) /* likely */
1958	case ABLEZ:
1959		return SP(0, 6)
1960	case -ABLEZ:
1961		return SP(2, 6) /* likely */
1962	case ABLTZ:
1963		return SP(0, 1) | BCOND(0, 0)
1964	case -ABLTZ:
1965		return SP(0, 1) | BCOND(0, 2) /* likely */
1966	case ABLTZAL:
1967		return SP(0, 1) | BCOND(2, 0)
1968	case -ABLTZAL:
1969		return SP(0, 1) | BCOND(2, 2) /* likely */
1970	case ABFPT:
1971		return SP(2, 1) | (257 << 16)
1972	case -ABFPT:
1973		return SP(2, 1) | (259 << 16) /* likely */
1974	case ABFPF:
1975		return SP(2, 1) | (256 << 16)
1976	case -ABFPF:
1977		return SP(2, 1) | (258 << 16) /* likely */
1978
1979	case AMOVB,
1980		AMOVBU:
1981		return SP(5, 0)
1982	case AMOVH,
1983		AMOVHU:
1984		return SP(5, 1)
1985	case AMOVW,
1986		AMOVWU:
1987		return SP(5, 3)
1988	case AMOVV:
1989		return SP(7, 7)
1990	case AMOVF:
1991		return SP(7, 1)
1992	case AMOVD:
1993		return SP(7, 5)
1994	case AMOVWL:
1995		return SP(5, 2)
1996	case AMOVWR:
1997		return SP(5, 6)
1998	case AMOVVL:
1999		return SP(5, 4)
2000	case AMOVVR:
2001		return SP(5, 5)
2002
2003	case ABREAK:
2004		return SP(5, 7)
2005
2006	case -AMOVWL:
2007		return SP(4, 2)
2008	case -AMOVWR:
2009		return SP(4, 6)
2010	case -AMOVVL:
2011		return SP(3, 2)
2012	case -AMOVVR:
2013		return SP(3, 3)
2014	case -AMOVB:
2015		return SP(4, 0)
2016	case -AMOVBU:
2017		return SP(4, 4)
2018	case -AMOVH:
2019		return SP(4, 1)
2020	case -AMOVHU:
2021		return SP(4, 5)
2022	case -AMOVW:
2023		return SP(4, 3)
2024	case -AMOVWU:
2025		return SP(4, 7)
2026	case -AMOVV:
2027		return SP(6, 7)
2028	case -AMOVF:
2029		return SP(6, 1)
2030	case -AMOVD:
2031		return SP(6, 5)
2032
2033	case ASLLV:
2034		return OP(7, 0)
2035	case ASRLV:
2036		return OP(7, 2)
2037	case ASRAV:
2038		return OP(7, 3)
2039	case AROTRV:
2040		return OP(7, 2) | 1<<21
2041	case -ASLLV:
2042		return OP(7, 4)
2043	case -ASRLV:
2044		return OP(7, 6)
2045	case -ASRAV:
2046		return OP(7, 7)
2047	case -AROTRV:
2048		return OP(7, 6) | 1<<21
2049
2050	case ATEQ:
2051		return OP(6, 4)
2052	case ATNE:
2053		return OP(6, 6)
2054	case -ALL:
2055		return SP(6, 0)
2056	case -ALLV:
2057		return SP(6, 4)
2058	case ASC:
2059		return SP(7, 0)
2060	case ASCV:
2061		return SP(7, 4)
2062	}
2063
2064	if a < 0 {
2065		c.ctxt.Diag("bad irr opcode -%v", -a)
2066	} else {
2067		c.ctxt.Diag("bad irr opcode %v", a)
2068	}
2069	return 0
2070}
2071
2072func vshift(a obj.As) bool {
2073	switch a {
2074	case ASLLV,
2075		ASRLV,
2076		ASRAV,
2077		AROTRV:
2078		return true
2079	}
2080	return false
2081}
2082
2083// MSA Two-bit Data Format Field Encoding
2084func (c *ctxt0) twobitdf(a obj.As) uint32 {
2085	switch a {
2086	case AVMOVB:
2087		return 0
2088	case AVMOVH:
2089		return 1
2090	case AVMOVW:
2091		return 2
2092	case AVMOVD:
2093		return 3
2094	default:
2095		c.ctxt.Diag("unsupported data format %v", a)
2096	}
2097	return 0
2098}
2099
2100// MSA Load/Store offset have to be multiple of size of data format
2101func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
2102	var mod int32
2103	switch a {
2104	case AVMOVB:
2105		mod = 1
2106	case AVMOVH:
2107		mod = 2
2108	case AVMOVW:
2109		mod = 4
2110	case AVMOVD:
2111		mod = 8
2112	default:
2113		c.ctxt.Diag("unsupported instruction:%v", a)
2114	}
2115
2116	if o%mod != 0 {
2117		c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
2118	}
2119
2120	return o / mod
2121}
2122