podman

Форк
0
2108 строк · 54.2 Кб
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
	"github.com/twitchyliquid64/golang-asm/obj"
34
	"github.com/twitchyliquid64/golang-asm/objabi"
35
	"github.com/twitchyliquid64/golang-asm/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.
44
type 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

55
const (
56
	mips64FuncAlign = 8
57
)
58

59
const (
60
	r0iszero = 1
61
)
62

63
type 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

75
const (
76
	// Optab.flag
77
	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
78
)
79

80
var 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

403
var oprange [ALAST & obj.AMask][]Optab
404

405
var xcmp [C_NCLASS][C_NCLASS]bool
406

407
func 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.
536
func (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.
544
func (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

559
func isint32(v int64) bool {
560
	return int64(int32(v)) == v
561
}
562

563
func isuint32(v uint64) bool {
564
	return uint64(uint32(v)) == v
565
}
566

567
func (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

745
func prasm(p *obj.Prog) {
746
	fmt.Printf("%v\n", p)
747
}
748

749
func (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

794
func 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

875
type ocmp []Optab
876

877
func (x ocmp) Len() int {
878
	return len(x)
879
}
880

881
func (x ocmp) Swap(i, j int) {
882
	x[i], x[j] = x[j], x[i]
883
}
884

885
func (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

907
func opset(a, b0 obj.As) {
908
	oprange[a&obj.AMask] = oprange[b0]
909
}
910

911
func 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

1026
		case ASLLV:
1027
			opset(ASRAV, r0)
1028
			opset(ASRLV, r0)
1029

1030
		case ASUB:
1031
			opset(ASUBU, r0)
1032
			opset(ANOR, r0)
1033

1034
		case ASUBV:
1035
			opset(ASUBVU, r0)
1036

1037
		case ASYSCALL:
1038
			opset(ASYNC, r0)
1039
			opset(ANOOP, r0)
1040
			opset(ATLBP, r0)
1041
			opset(ATLBR, r0)
1042
			opset(ATLBWI, r0)
1043
			opset(ATLBWR, r0)
1044

1045
		case ACMPEQF:
1046
			opset(ACMPGTF, r0)
1047
			opset(ACMPGTD, r0)
1048
			opset(ACMPGEF, r0)
1049
			opset(ACMPGED, r0)
1050
			opset(ACMPEQD, r0)
1051

1052
		case ABFPT:
1053
			opset(ABFPF, r0)
1054

1055
		case AMOVWL:
1056
			opset(AMOVWR, r0)
1057

1058
		case AMOVVL:
1059
			opset(AMOVVR, r0)
1060

1061
		case AVMOVB:
1062
			opset(AVMOVH, r0)
1063
			opset(AVMOVW, r0)
1064
			opset(AVMOVD, r0)
1065

1066
		case AMOVW,
1067
			AMOVD,
1068
			AMOVF,
1069
			AMOVV,
1070
			ABREAK,
1071
			ARFE,
1072
			AJAL,
1073
			AJMP,
1074
			AMOVWU,
1075
			ALL,
1076
			ALLV,
1077
			ASC,
1078
			ASCV,
1079
			ANEGW,
1080
			ANEGV,
1081
			AWORD,
1082
			obj.ANOP,
1083
			obj.ATEXT,
1084
			obj.AUNDEF,
1085
			obj.AFUNCDATA,
1086
			obj.APCDATA,
1087
			obj.ADUFFZERO,
1088
			obj.ADUFFCOPY:
1089
			break
1090

1091
		case ACMOVN:
1092
			opset(ACMOVZ, r0)
1093

1094
		case ACMOVT:
1095
			opset(ACMOVF, r0)
1096

1097
		case ACLO:
1098
			opset(ACLZ, r0)
1099

1100
		case ATEQ:
1101
			opset(ATNE, r0)
1102
		}
1103
	}
1104
}
1105

1106
func OP(x uint32, y uint32) uint32 {
1107
	return x<<3 | y<<0
1108
}
1109

1110
func SP(x uint32, y uint32) uint32 {
1111
	return x<<29 | y<<26
1112
}
1113

1114
func BCOND(x uint32, y uint32) uint32 {
1115
	return x<<19 | y<<16
1116
}
1117

1118
func MMU(x uint32, y uint32) uint32 {
1119
	return SP(2, 0) | 16<<21 | x<<3 | y<<0
1120
}
1121

1122
func FPF(x uint32, y uint32) uint32 {
1123
	return SP(2, 1) | 16<<21 | x<<3 | y<<0
1124
}
1125

1126
func FPD(x uint32, y uint32) uint32 {
1127
	return SP(2, 1) | 17<<21 | x<<3 | y<<0
1128
}
1129

1130
func FPW(x uint32, y uint32) uint32 {
1131
	return SP(2, 1) | 20<<21 | x<<3 | y<<0
1132
}
1133

1134
func FPV(x uint32, y uint32) uint32 {
1135
	return SP(2, 1) | 21<<21 | x<<3 | y<<0
1136
}
1137

1138
func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1139
	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
1140
}
1141

1142
func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
1143
	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
1144
}
1145

1146
func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
1147
	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
1148
}
1149

1150
func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1151
	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
1152
}
1153

1154
func OP_JMP(op uint32, i uint32) uint32 {
1155
	return op | i&0x3FFFFFF
1156
}
1157

1158
func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
1159
	return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
1160
}
1161

1162
func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
1163
	return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
1164
}
1165

1166
func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1167
	o1 := uint32(0)
1168
	o2 := uint32(0)
1169
	o3 := uint32(0)
1170
	o4 := uint32(0)
1171

1172
	add := AADDU
1173

1174
	if c.ctxt.Arch.Family == sys.MIPS64 {
1175
		add = AADDVU
1176
	}
1177
	switch o.type_ {
1178
	default:
1179
		c.ctxt.Diag("unknown type %d %v", o.type_)
1180
		prasm(p)
1181

1182
	case 0: /* pseudo ops */
1183
		break
1184

1185
	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
1186
		a := AOR
1187
		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
1188
			// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
1189
			// but SLL is special that the result is always sign-extended to 64-bit.
1190
			a = ASLL
1191
		}
1192
		o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
1193

1194
	case 2: /* add/sub r1,[r2],r3 */
1195
		r := int(p.Reg)
1196
		if p.As == ANEGW || p.As == ANEGV {
1197
			r = REGZERO
1198
		}
1199
		if r == 0 {
1200
			r = int(p.To.Reg)
1201
		}
1202
		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1203

1204
	case 3: /* mov $soreg, r ==> or/add $i,o,r */
1205
		v := c.regoff(&p.From)
1206

1207
		r := int(p.From.Reg)
1208
		if r == 0 {
1209
			r = int(o.param)
1210
		}
1211
		a := add
1212
		if o.a1 == C_ANDCON {
1213
			a = AOR
1214
		}
1215

1216
		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1217

1218
	case 4: /* add $scon,[r1],r2 */
1219
		v := c.regoff(&p.From)
1220

1221
		r := int(p.Reg)
1222
		if r == 0 {
1223
			r = int(p.To.Reg)
1224
		}
1225

1226
		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1227

1228
	case 5: /* syscall */
1229
		o1 = c.oprrr(p.As)
1230

1231
	case 6: /* beq r1,[r2],sbra */
1232
		v := int32(0)
1233
		if p.To.Target() == nil {
1234
			v = int32(-4) >> 2
1235
		} else {
1236
			v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1237
		}
1238
		if (v<<16)>>16 != v {
1239
			c.ctxt.Diag("short branch too far\n%v", p)
1240
		}
1241
		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
1242
		// for ABFPT and ABFPF only: always fill delay slot with 0
1243
		// see comments in func preprocess for details.
1244
		o2 = 0
1245

1246
	case 7: /* mov r, soreg ==> sw o(r) */
1247
		r := int(p.To.Reg)
1248
		if r == 0 {
1249
			r = int(o.param)
1250
		}
1251
		v := c.regoff(&p.To)
1252
		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1253

1254
	case 8: /* mov soreg, r ==> lw o(r) */
1255
		r := int(p.From.Reg)
1256
		if r == 0 {
1257
			r = int(o.param)
1258
		}
1259
		v := c.regoff(&p.From)
1260
		o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1261

1262
	case 9: /* sll r1,[r2],r3 */
1263
		r := int(p.Reg)
1264

1265
		if r == 0 {
1266
			r = int(p.To.Reg)
1267
		}
1268
		o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
1269

1270
	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
1271
		v := c.regoff(&p.From)
1272
		a := AOR
1273
		if v < 0 {
1274
			a = AADDU
1275
		}
1276
		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1277
		r := int(p.Reg)
1278
		if r == 0 {
1279
			r = int(p.To.Reg)
1280
		}
1281
		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1282

1283
	case 11: /* jmp lbra */
1284
		v := int32(0)
1285
		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
1286
			// use PC-relative branch for short branches
1287
			// BEQ	R0, R0, sbra
1288
			if p.To.Target() == nil {
1289
				v = int32(-4) >> 2
1290
			} else {
1291
				v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1292
			}
1293
			if (v<<16)>>16 == v {
1294
				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
1295
				break
1296
			}
1297
		}
1298
		if p.To.Target() == nil {
1299
			v = int32(p.Pc) >> 2
1300
		} else {
1301
			v = int32(p.To.Target().Pc) >> 2
1302
		}
1303
		o1 = OP_JMP(c.opirr(p.As), uint32(v))
1304
		if p.To.Sym == nil {
1305
			p.To.Sym = c.cursym.Func.Text.From.Sym
1306
			p.To.Offset = p.To.Target().Pc
1307
		}
1308
		rel := obj.Addrel(c.cursym)
1309
		rel.Off = int32(c.pc)
1310
		rel.Siz = 4
1311
		rel.Sym = p.To.Sym
1312
		rel.Add = p.To.Offset
1313
		if p.As == AJAL {
1314
			rel.Type = objabi.R_CALLMIPS
1315
		} else {
1316
			rel.Type = objabi.R_JMPMIPS
1317
		}
1318

1319
	case 12: /* movbs r,r */
1320
		// NOTE: this case does not use REGTMP. If it ever does,
1321
		// remove the NOTUSETMP flag in optab.
1322
		v := 16
1323
		if p.As == AMOVB {
1324
			v = 24
1325
		}
1326
		o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
1327
		o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1328

1329
	case 13: /* movbu r,r */
1330
		if p.As == AMOVBU {
1331
			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1332
		} else {
1333
			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
1334
		}
1335

1336
	case 14: /* movwu r,r */
1337
		// NOTE: this case does not use REGTMP. If it ever does,
1338
		// remove the NOTUSETMP flag in optab.
1339
		o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1340
		o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1341

1342
	case 15: /* teq $c r,r */
1343
		v := c.regoff(&p.From)
1344
		r := int(p.Reg)
1345
		if r == 0 {
1346
			r = REGZERO
1347
		}
1348
		/* only use 10 bits of trap code */
1349
		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
1350

1351
	case 16: /* sll $c,[r1],r2 */
1352
		v := c.regoff(&p.From)
1353
		r := int(p.Reg)
1354
		if r == 0 {
1355
			r = int(p.To.Reg)
1356
		}
1357

1358
		/* OP_SRR will use only the low 5 bits of the shift value */
1359
		if v >= 32 && vshift(p.As) {
1360
			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
1361
		} else {
1362
			o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1363
		}
1364

1365
	case 17:
1366
		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
1367

1368
	case 18: /* jmp [r1],0(r2) */
1369
		r := int(p.Reg)
1370
		if r == 0 {
1371
			r = int(o.param)
1372
		}
1373
		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
1374
		if p.As == obj.ACALL {
1375
			rel := obj.Addrel(c.cursym)
1376
			rel.Off = int32(c.pc)
1377
			rel.Siz = 0
1378
			rel.Type = objabi.R_CALLIND
1379
		}
1380

1381
	case 19: /* mov $lcon,r ==> lu+or */
1382
		// NOTE: this case does not use REGTMP. If it ever does,
1383
		// remove the NOTUSETMP flag in optab.
1384
		v := c.regoff(&p.From)
1385
		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1386
		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1387

1388
	case 20: /* mov lo/hi,r */
1389
		a := OP(2, 0) /* mfhi */
1390
		if p.From.Reg == REG_LO {
1391
			a = OP(2, 2) /* mflo */
1392
		}
1393
		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
1394

1395
	case 21: /* mov r,lo/hi */
1396
		a := OP(2, 1) /* mthi */
1397
		if p.To.Reg == REG_LO {
1398
			a = OP(2, 3) /* mtlo */
1399
		}
1400
		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
1401

1402
	case 22: /* mul r1,r2 [r3]*/
1403
		if p.To.Reg != 0 {
1404
			r := int(p.Reg)
1405
			if r == 0 {
1406
				r = int(p.To.Reg)
1407
			}
1408
			a := SP(3, 4) | 2 /* mul */
1409
			o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1410
		} else {
1411
			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
1412
		}
1413

1414
	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
1415
		v := c.regoff(&p.From)
1416
		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1417
		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1418
		r := int(p.Reg)
1419
		if r == 0 {
1420
			r = int(p.To.Reg)
1421
		}
1422
		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1423

1424
	case 24: /* mov $ucon,r ==> lu r */
1425
		v := c.regoff(&p.From)
1426
		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1427

1428
	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
1429
		v := c.regoff(&p.From)
1430
		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1431
		r := int(p.Reg)
1432
		if r == 0 {
1433
			r = int(p.To.Reg)
1434
		}
1435
		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1436

1437
	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
1438
		v := c.regoff(&p.From)
1439
		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1440
		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1441
		r := int(p.From.Reg)
1442
		if r == 0 {
1443
			r = int(o.param)
1444
		}
1445
		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1446

1447
	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1448
		v := c.regoff(&p.From)
1449
		r := int(p.From.Reg)
1450
		if r == 0 {
1451
			r = int(o.param)
1452
		}
1453
		a := -AMOVF
1454
		if p.As == AMOVD {
1455
			a = -AMOVD
1456
		}
1457
		switch o.size {
1458
		case 12:
1459
			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1460
			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1461
			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1462

1463
		case 4:
1464
			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1465
		}
1466

1467
	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1468
		v := c.regoff(&p.To)
1469
		r := int(p.To.Reg)
1470
		if r == 0 {
1471
			r = int(o.param)
1472
		}
1473
		a := AMOVF
1474
		if p.As == AMOVD {
1475
			a = AMOVD
1476
		}
1477
		switch o.size {
1478
		case 12:
1479
			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1480
			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1481
			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1482

1483
		case 4:
1484
			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
1485
		}
1486

1487
	case 30: /* movw r,fr */
1488
		a := SP(2, 1) | (4 << 21) /* mtc1 */
1489
		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1490

1491
	case 31: /* movw fr,r */
1492
		a := SP(2, 1) | (0 << 21) /* mtc1 */
1493
		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1494

1495
	case 32: /* fadd fr1,[fr2],fr3 */
1496
		r := int(p.Reg)
1497
		if r == 0 {
1498
			r = int(p.To.Reg)
1499
		}
1500
		o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1501

1502
	case 33: /* fabs fr1, fr3 */
1503
		o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1504

1505
	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
1506
		v := c.regoff(&p.From)
1507
		a := AADDU
1508
		if o.a1 == C_ANDCON {
1509
			a = AOR
1510
		}
1511
		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1512
		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
1513

1514
	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
1515
		v := c.regoff(&p.To)
1516
		r := int(p.To.Reg)
1517
		if r == 0 {
1518
			r = int(o.param)
1519
		}
1520
		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1521
		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1522
		o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1523

1524
	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
1525
		v := c.regoff(&p.From)
1526
		r := int(p.From.Reg)
1527
		if r == 0 {
1528
			r = int(o.param)
1529
		}
1530
		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1531
		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1532
		o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1533

1534
	case 37: /* movw r,mr */
1535
		a := SP(2, 0) | (4 << 21) /* mtc0 */
1536
		if p.As == AMOVV {
1537
			a = SP(2, 0) | (5 << 21) /* dmtc0 */
1538
		}
1539
		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1540

1541
	case 38: /* movw mr,r */
1542
		a := SP(2, 0) | (0 << 21) /* mfc0 */
1543
		if p.As == AMOVV {
1544
			a = SP(2, 0) | (1 << 21) /* dmfc0 */
1545
		}
1546
		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1547

1548
	case 40: /* word */
1549
		o1 = uint32(c.regoff(&p.From))
1550

1551
	case 41: /* movw f,fcr */
1552
		o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
1553

1554
	case 42: /* movw fcr,r */
1555
		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
1556

1557
	case 47: /* movv r,fr */
1558
		a := SP(2, 1) | (5 << 21) /* dmtc1 */
1559
		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1560

1561
	case 48: /* movv fr,r */
1562
		a := SP(2, 1) | (1 << 21) /* dmtc1 */
1563
		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1564

1565
	case 49: /* undef */
1566
		o1 = 52 /* trap -- teq r0, r0 */
1567

1568
	/* relocation operations */
1569
	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
1570
		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1571
		rel := obj.Addrel(c.cursym)
1572
		rel.Off = int32(c.pc)
1573
		rel.Siz = 4
1574
		rel.Sym = p.To.Sym
1575
		rel.Add = p.To.Offset
1576
		rel.Type = objabi.R_ADDRMIPSU
1577
		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1578
		rel2 := obj.Addrel(c.cursym)
1579
		rel2.Off = int32(c.pc + 4)
1580
		rel2.Siz = 4
1581
		rel2.Sym = p.To.Sym
1582
		rel2.Add = p.To.Offset
1583
		rel2.Type = objabi.R_ADDRMIPS
1584

1585
		if o.size == 12 {
1586
			o3 = o2
1587
			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1588
			rel2.Off += 4
1589
		}
1590

1591
	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
1592
		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1593
		rel := obj.Addrel(c.cursym)
1594
		rel.Off = int32(c.pc)
1595
		rel.Siz = 4
1596
		rel.Sym = p.From.Sym
1597
		rel.Add = p.From.Offset
1598
		rel.Type = objabi.R_ADDRMIPSU
1599
		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1600
		rel2 := obj.Addrel(c.cursym)
1601
		rel2.Off = int32(c.pc + 4)
1602
		rel2.Siz = 4
1603
		rel2.Sym = p.From.Sym
1604
		rel2.Add = p.From.Offset
1605
		rel2.Type = objabi.R_ADDRMIPS
1606

1607
		if o.size == 12 {
1608
			o3 = o2
1609
			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1610
			rel2.Off += 4
1611
		}
1612

1613
	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
1614
		// NOTE: this case does not use REGTMP. If it ever does,
1615
		// remove the NOTUSETMP flag in optab.
1616
		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
1617
		rel := obj.Addrel(c.cursym)
1618
		rel.Off = int32(c.pc)
1619
		rel.Siz = 4
1620
		rel.Sym = p.From.Sym
1621
		rel.Add = p.From.Offset
1622
		rel.Type = objabi.R_ADDRMIPSU
1623
		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1624
		rel2 := obj.Addrel(c.cursym)
1625
		rel2.Off = int32(c.pc + 4)
1626
		rel2.Siz = 4
1627
		rel2.Sym = p.From.Sym
1628
		rel2.Add = p.From.Offset
1629
		rel2.Type = objabi.R_ADDRMIPS
1630

1631
		if o.size == 12 {
1632
			o3 = o2
1633
			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
1634
			rel2.Off += 4
1635
		}
1636

1637
	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1638
		// clobbers R3 !
1639
		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
1640
		// NOTE: this case does not use REGTMP. If it ever does,
1641
		// remove the NOTUSETMP flag in optab.
1642
		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1643
		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
1644
		rel := obj.Addrel(c.cursym)
1645
		rel.Off = int32(c.pc + 4)
1646
		rel.Siz = 4
1647
		rel.Sym = p.To.Sym
1648
		rel.Add = p.To.Offset
1649
		rel.Type = objabi.R_ADDRMIPSTLS
1650

1651
	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1652
		// clobbers R3 !
1653
		// NOTE: this case does not use REGTMP. If it ever does,
1654
		// remove the NOTUSETMP flag in optab.
1655
		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1656
		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1657
		rel := obj.Addrel(c.cursym)
1658
		rel.Off = int32(c.pc + 4)
1659
		rel.Siz = 4
1660
		rel.Sym = p.From.Sym
1661
		rel.Add = p.From.Offset
1662
		rel.Type = objabi.R_ADDRMIPSTLS
1663

1664
	case 55: /* mov $tlsvar, r ==> rdhwr + add */
1665
		// clobbers R3 !
1666
		// NOTE: this case does not use REGTMP. If it ever does,
1667
		// remove the NOTUSETMP flag in optab.
1668
		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1669
		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1670
		rel := obj.Addrel(c.cursym)
1671
		rel.Off = int32(c.pc + 4)
1672
		rel.Siz = 4
1673
		rel.Sym = p.From.Sym
1674
		rel.Add = p.From.Offset
1675
		rel.Type = objabi.R_ADDRMIPSTLS
1676

1677
	case 56: /* vmov{b,h,w,d} $scon, wr */
1678

1679
		v := c.regoff(&p.From)
1680
		o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
1681

1682
	case 57: /* vld $soreg, wr */
1683
		v := c.lsoffset(p.As, c.regoff(&p.From))
1684
		o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
1685

1686
	case 58: /* vst wr, $soreg */
1687
		v := c.lsoffset(p.As, c.regoff(&p.To))
1688
		o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
1689
	}
1690

1691
	out[0] = o1
1692
	out[1] = o2
1693
	out[2] = o3
1694
	out[3] = o4
1695
}
1696

1697
func (c *ctxt0) vregoff(a *obj.Addr) int64 {
1698
	c.instoffset = 0
1699
	c.aclass(a)
1700
	return c.instoffset
1701
}
1702

1703
func (c *ctxt0) regoff(a *obj.Addr) int32 {
1704
	return int32(c.vregoff(a))
1705
}
1706

1707
func (c *ctxt0) oprrr(a obj.As) uint32 {
1708
	switch a {
1709
	case AADD:
1710
		return OP(4, 0)
1711
	case AADDU:
1712
		return OP(4, 1)
1713
	case ASGT:
1714
		return OP(5, 2)
1715
	case ASGTU:
1716
		return OP(5, 3)
1717
	case AAND:
1718
		return OP(4, 4)
1719
	case AOR:
1720
		return OP(4, 5)
1721
	case AXOR:
1722
		return OP(4, 6)
1723
	case ASUB:
1724
		return OP(4, 2)
1725
	case ASUBU, ANEGW:
1726
		return OP(4, 3)
1727
	case ANOR:
1728
		return OP(4, 7)
1729
	case ASLL:
1730
		return OP(0, 4)
1731
	case ASRL:
1732
		return OP(0, 6)
1733
	case ASRA:
1734
		return OP(0, 7)
1735
	case ASLLV:
1736
		return OP(2, 4)
1737
	case ASRLV:
1738
		return OP(2, 6)
1739
	case ASRAV:
1740
		return OP(2, 7)
1741
	case AADDV:
1742
		return OP(5, 4)
1743
	case AADDVU:
1744
		return OP(5, 5)
1745
	case ASUBV:
1746
		return OP(5, 6)
1747
	case ASUBVU, ANEGV:
1748
		return OP(5, 7)
1749
	case AREM,
1750
		ADIV:
1751
		return OP(3, 2)
1752
	case AREMU,
1753
		ADIVU:
1754
		return OP(3, 3)
1755
	case AMUL:
1756
		return OP(3, 0)
1757
	case AMULU:
1758
		return OP(3, 1)
1759
	case AREMV,
1760
		ADIVV:
1761
		return OP(3, 6)
1762
	case AREMVU,
1763
		ADIVVU:
1764
		return OP(3, 7)
1765
	case AMULV:
1766
		return OP(3, 4)
1767
	case AMULVU:
1768
		return OP(3, 5)
1769

1770
	case AJMP:
1771
		return OP(1, 0)
1772
	case AJAL:
1773
		return OP(1, 1)
1774

1775
	case ABREAK:
1776
		return OP(1, 5)
1777
	case ASYSCALL:
1778
		return OP(1, 4)
1779
	case ATLBP:
1780
		return MMU(1, 0)
1781
	case ATLBR:
1782
		return MMU(0, 1)
1783
	case ATLBWI:
1784
		return MMU(0, 2)
1785
	case ATLBWR:
1786
		return MMU(0, 6)
1787
	case ARFE:
1788
		return MMU(2, 0)
1789

1790
	case ADIVF:
1791
		return FPF(0, 3)
1792
	case ADIVD:
1793
		return FPD(0, 3)
1794
	case AMULF:
1795
		return FPF(0, 2)
1796
	case AMULD:
1797
		return FPD(0, 2)
1798
	case ASUBF:
1799
		return FPF(0, 1)
1800
	case ASUBD:
1801
		return FPD(0, 1)
1802
	case AADDF:
1803
		return FPF(0, 0)
1804
	case AADDD:
1805
		return FPD(0, 0)
1806
	case ATRUNCFV:
1807
		return FPF(1, 1)
1808
	case ATRUNCDV:
1809
		return FPD(1, 1)
1810
	case ATRUNCFW:
1811
		return FPF(1, 5)
1812
	case ATRUNCDW:
1813
		return FPD(1, 5)
1814
	case AMOVFV:
1815
		return FPF(4, 5)
1816
	case AMOVDV:
1817
		return FPD(4, 5)
1818
	case AMOVVF:
1819
		return FPV(4, 0)
1820
	case AMOVVD:
1821
		return FPV(4, 1)
1822
	case AMOVFW:
1823
		return FPF(4, 4)
1824
	case AMOVDW:
1825
		return FPD(4, 4)
1826
	case AMOVWF:
1827
		return FPW(4, 0)
1828
	case AMOVDF:
1829
		return FPD(4, 0)
1830
	case AMOVWD:
1831
		return FPW(4, 1)
1832
	case AMOVFD:
1833
		return FPF(4, 1)
1834
	case AABSF:
1835
		return FPF(0, 5)
1836
	case AABSD:
1837
		return FPD(0, 5)
1838
	case AMOVF:
1839
		return FPF(0, 6)
1840
	case AMOVD:
1841
		return FPD(0, 6)
1842
	case ANEGF:
1843
		return FPF(0, 7)
1844
	case ANEGD:
1845
		return FPD(0, 7)
1846
	case ACMPEQF:
1847
		return FPF(6, 2)
1848
	case ACMPEQD:
1849
		return FPD(6, 2)
1850
	case ACMPGTF:
1851
		return FPF(7, 4)
1852
	case ACMPGTD:
1853
		return FPD(7, 4)
1854
	case ACMPGEF:
1855
		return FPF(7, 6)
1856
	case ACMPGED:
1857
		return FPD(7, 6)
1858

1859
	case ASQRTF:
1860
		return FPF(0, 4)
1861
	case ASQRTD:
1862
		return FPD(0, 4)
1863

1864
	case ASYNC:
1865
		return OP(1, 7)
1866
	case ANOOP:
1867
		return 0
1868

1869
	case ACMOVN:
1870
		return OP(1, 3)
1871
	case ACMOVZ:
1872
		return OP(1, 2)
1873
	case ACMOVT:
1874
		return OP(0, 1) | (1 << 16)
1875
	case ACMOVF:
1876
		return OP(0, 1) | (0 << 16)
1877
	case ACLO:
1878
		return SP(3, 4) | OP(4, 1)
1879
	case ACLZ:
1880
		return SP(3, 4) | OP(4, 0)
1881
	case AMADD:
1882
		return SP(3, 4) | OP(0, 0)
1883
	case AMSUB:
1884
		return SP(3, 4) | OP(0, 4)
1885
	}
1886

1887
	if a < 0 {
1888
		c.ctxt.Diag("bad rrr opcode -%v", -a)
1889
	} else {
1890
		c.ctxt.Diag("bad rrr opcode %v", a)
1891
	}
1892
	return 0
1893
}
1894

1895
func (c *ctxt0) opirr(a obj.As) uint32 {
1896
	switch a {
1897
	case AADD:
1898
		return SP(1, 0)
1899
	case AADDU:
1900
		return SP(1, 1)
1901
	case ASGT:
1902
		return SP(1, 2)
1903
	case ASGTU:
1904
		return SP(1, 3)
1905
	case AAND:
1906
		return SP(1, 4)
1907
	case AOR:
1908
		return SP(1, 5)
1909
	case AXOR:
1910
		return SP(1, 6)
1911
	case ALUI:
1912
		return SP(1, 7)
1913
	case ASLL:
1914
		return OP(0, 0)
1915
	case ASRL:
1916
		return OP(0, 2)
1917
	case ASRA:
1918
		return OP(0, 3)
1919
	case AADDV:
1920
		return SP(3, 0)
1921
	case AADDVU:
1922
		return SP(3, 1)
1923

1924
	case AJMP:
1925
		return SP(0, 2)
1926
	case AJAL,
1927
		obj.ADUFFZERO,
1928
		obj.ADUFFCOPY:
1929
		return SP(0, 3)
1930
	case ABEQ:
1931
		return SP(0, 4)
1932
	case -ABEQ:
1933
		return SP(2, 4) /* likely */
1934
	case ABNE:
1935
		return SP(0, 5)
1936
	case -ABNE:
1937
		return SP(2, 5) /* likely */
1938
	case ABGEZ:
1939
		return SP(0, 1) | BCOND(0, 1)
1940
	case -ABGEZ:
1941
		return SP(0, 1) | BCOND(0, 3) /* likely */
1942
	case ABGEZAL:
1943
		return SP(0, 1) | BCOND(2, 1)
1944
	case -ABGEZAL:
1945
		return SP(0, 1) | BCOND(2, 3) /* likely */
1946
	case ABGTZ:
1947
		return SP(0, 7)
1948
	case -ABGTZ:
1949
		return SP(2, 7) /* likely */
1950
	case ABLEZ:
1951
		return SP(0, 6)
1952
	case -ABLEZ:
1953
		return SP(2, 6) /* likely */
1954
	case ABLTZ:
1955
		return SP(0, 1) | BCOND(0, 0)
1956
	case -ABLTZ:
1957
		return SP(0, 1) | BCOND(0, 2) /* likely */
1958
	case ABLTZAL:
1959
		return SP(0, 1) | BCOND(2, 0)
1960
	case -ABLTZAL:
1961
		return SP(0, 1) | BCOND(2, 2) /* likely */
1962
	case ABFPT:
1963
		return SP(2, 1) | (257 << 16)
1964
	case -ABFPT:
1965
		return SP(2, 1) | (259 << 16) /* likely */
1966
	case ABFPF:
1967
		return SP(2, 1) | (256 << 16)
1968
	case -ABFPF:
1969
		return SP(2, 1) | (258 << 16) /* likely */
1970

1971
	case AMOVB,
1972
		AMOVBU:
1973
		return SP(5, 0)
1974
	case AMOVH,
1975
		AMOVHU:
1976
		return SP(5, 1)
1977
	case AMOVW,
1978
		AMOVWU:
1979
		return SP(5, 3)
1980
	case AMOVV:
1981
		return SP(7, 7)
1982
	case AMOVF:
1983
		return SP(7, 1)
1984
	case AMOVD:
1985
		return SP(7, 5)
1986
	case AMOVWL:
1987
		return SP(5, 2)
1988
	case AMOVWR:
1989
		return SP(5, 6)
1990
	case AMOVVL:
1991
		return SP(5, 4)
1992
	case AMOVVR:
1993
		return SP(5, 5)
1994

1995
	case ABREAK:
1996
		return SP(5, 7)
1997

1998
	case -AMOVWL:
1999
		return SP(4, 2)
2000
	case -AMOVWR:
2001
		return SP(4, 6)
2002
	case -AMOVVL:
2003
		return SP(3, 2)
2004
	case -AMOVVR:
2005
		return SP(3, 3)
2006
	case -AMOVB:
2007
		return SP(4, 0)
2008
	case -AMOVBU:
2009
		return SP(4, 4)
2010
	case -AMOVH:
2011
		return SP(4, 1)
2012
	case -AMOVHU:
2013
		return SP(4, 5)
2014
	case -AMOVW:
2015
		return SP(4, 3)
2016
	case -AMOVWU:
2017
		return SP(4, 7)
2018
	case -AMOVV:
2019
		return SP(6, 7)
2020
	case -AMOVF:
2021
		return SP(6, 1)
2022
	case -AMOVD:
2023
		return SP(6, 5)
2024

2025
	case ASLLV:
2026
		return OP(7, 0)
2027
	case ASRLV:
2028
		return OP(7, 2)
2029
	case ASRAV:
2030
		return OP(7, 3)
2031
	case -ASLLV:
2032
		return OP(7, 4)
2033
	case -ASRLV:
2034
		return OP(7, 6)
2035
	case -ASRAV:
2036
		return OP(7, 7)
2037

2038
	case ATEQ:
2039
		return OP(6, 4)
2040
	case ATNE:
2041
		return OP(6, 6)
2042
	case -ALL:
2043
		return SP(6, 0)
2044
	case -ALLV:
2045
		return SP(6, 4)
2046
	case ASC:
2047
		return SP(7, 0)
2048
	case ASCV:
2049
		return SP(7, 4)
2050
	}
2051

2052
	if a < 0 {
2053
		c.ctxt.Diag("bad irr opcode -%v", -a)
2054
	} else {
2055
		c.ctxt.Diag("bad irr opcode %v", a)
2056
	}
2057
	return 0
2058
}
2059

2060
func vshift(a obj.As) bool {
2061
	switch a {
2062
	case ASLLV,
2063
		ASRLV,
2064
		ASRAV:
2065
		return true
2066
	}
2067
	return false
2068
}
2069

2070
// MSA Two-bit Data Format Field Encoding
2071
func (c *ctxt0) twobitdf(a obj.As) uint32 {
2072
	switch a {
2073
	case AVMOVB:
2074
		return 0
2075
	case AVMOVH:
2076
		return 1
2077
	case AVMOVW:
2078
		return 2
2079
	case AVMOVD:
2080
		return 3
2081
	default:
2082
		c.ctxt.Diag("unsupported data format %v", a)
2083
	}
2084
	return 0
2085
}
2086

2087
// MSA Load/Store offset have to be multiple of size of data format
2088
func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
2089
	var mod int32
2090
	switch a {
2091
	case AVMOVB:
2092
		mod = 1
2093
	case AVMOVH:
2094
		mod = 2
2095
	case AVMOVW:
2096
		mod = 4
2097
	case AVMOVD:
2098
		mod = 8
2099
	default:
2100
		c.ctxt.Diag("unsupported instruction:%v", a)
2101
	}
2102

2103
	if o%mod != 0 {
2104
		c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
2105
	}
2106

2107
	return o / mod
2108
}
2109

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.