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