1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package loong64
6
7import (
8	"cmd/internal/obj"
9	"cmd/internal/objabi"
10	"fmt"
11	"log"
12	"sort"
13)
14
15// ctxt0 holds state while assembling a single function.
16// Each function gets a fresh ctxt0.
17// This allows for multiple functions to be safely concurrently assembled.
18type ctxt0 struct {
19	ctxt       *obj.Link
20	newprog    obj.ProgAlloc
21	cursym     *obj.LSym
22	autosize   int32
23	instoffset int64
24	pc         int64
25}
26
27// Instruction layout.
28
29const (
30	FuncAlign = 4
31	loopAlign = 16
32)
33
34type Optab struct {
35	as    obj.As
36	from1 uint8
37	reg   uint8
38	from3 uint8
39	to1   uint8
40	to2   uint8
41	type_ int8
42	size  int8
43	param int16
44	flag  uint8
45}
46
47const (
48	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
49
50	// branchLoopHead marks loop entry.
51	// Used to insert padding for under-aligned loops.
52	branchLoopHead
53)
54
55var optab = []Optab{
56	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, C_NONE, 0, 0, 0, 0},
57
58	{AMOVW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
59	{AMOVV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
60	{AMOVB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 12, 8, 0, NOTUSETMP},
61	{AMOVBU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 13, 4, 0, 0},
62	{AMOVWU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 14, 8, 0, NOTUSETMP},
63
64	{ASUB, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
65	{ASUBV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
66	{AADD, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
67	{AADDV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
68	{AAND, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
69	{ASUB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
70	{ASUBV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
71	{AADD, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
72	{AADDV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
73	{AAND, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
74	{ANEGW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
75	{ANEGV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
76	{AMASKEQZ, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
77
78	{ASLL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
79	{ASLL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
80	{ASLLV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
81	{ASLLV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
82	{ACLO, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
83
84	{AADDF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 32, 4, 0, 0},
85	{AADDF, C_FREG, C_REG, C_NONE, C_FREG, C_NONE, 32, 4, 0, 0},
86	{ACMPEQF, C_FREG, C_REG, C_NONE, C_NONE, C_NONE, 32, 4, 0, 0},
87	{AABSF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
88	{AMOVVF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
89	{AMOVF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
90	{AMOVD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
91
92	{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
93	{AMOVWU, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
94	{AMOVV, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
95	{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
96	{AMOVBU, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
97	{AMOVWL, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
98	{AMOVVL, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
99	{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
100	{AMOVWU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
101	{AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
102	{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
103	{AMOVBU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
104	{AMOVWL, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
105	{AMOVVL, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
106	{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
107	{AMOVWU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
108	{AMOVV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
109	{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
110	{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
111	{AMOVWL, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
112	{AMOVVL, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
113	{ASC, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
114	{ASCV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
115
116	{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
117	{AMOVWU, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
118	{AMOVV, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
119	{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
120	{AMOVBU, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
121	{AMOVWL, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
122	{AMOVVL, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
123	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
124	{AMOVWU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
125	{AMOVV, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
126	{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
127	{AMOVBU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
128	{AMOVWL, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
129	{AMOVVL, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
130	{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
131	{AMOVWU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
132	{AMOVV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
133	{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
134	{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
135	{AMOVWL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
136	{AMOVVL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
137	{ALL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
138	{ALLV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
139
140	{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
141	{AMOVWU, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
142	{AMOVV, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
143	{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
144	{AMOVBU, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
145	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
146	{AMOVWU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
147	{AMOVV, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
148	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
149	{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
150	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
151	{AMOVWU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
152	{AMOVV, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
153	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
154	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
155	{ASC, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
156	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
157	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
158	{AMOVWU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
159	{AMOVV, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
160	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
161	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
162	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
163	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
164	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
165	{AMOVWU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
166	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
167	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
168	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
169
170	{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
171	{AMOVWU, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
172	{AMOVV, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
173	{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
174	{AMOVBU, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
175	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
176	{AMOVWU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
177	{AMOVV, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
178	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
179	{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
180	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
181	{AMOVWU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
182	{AMOVV, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
183	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
184	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
185	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
186	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
187	{AMOVWU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
188	{AMOVV, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
189	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
190	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
191	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
192	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
193	{AMOVW, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
194	{AMOVWU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
195	{AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
196	{AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
197	{AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
198
199	{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, 0, 0},
200	{AMOVV, C_SECON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, 0, 0},
201	{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
202	{AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
203	{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
204	{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
205	{AMOVV, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
206
207	{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 26, 12, REGSP, 0},
208	{AMOVV, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 26, 12, REGSP, 0},
209	{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
210	{AMOVV, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
211	{AMOVW, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
212	{AMOVV, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
213	{AMOVW, C_STCON, C_NONE, C_NONE, C_REG, C_NONE, 55, 12, 0, 0},
214	{AMOVV, C_STCON, C_NONE, C_NONE, C_REG, C_NONE, 55, 12, 0, 0},
215
216	{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 24, 4, 0, 0},
217	{AMOVV, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 24, 4, 0, 0},
218	{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
219	{AMOVV, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
220	{AMOVV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 59, 16, 0, NOTUSETMP},
221
222	{AMUL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
223	{AMUL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
224	{AMULV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
225	{AMULV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
226
227	{AADD, C_ADD0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
228	{AADD, C_ADD0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
229	{AADD, C_ANDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
230	{AADD, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
231
232	{AADDV, C_ADD0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
233	{AADDV, C_ADD0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
234	{AADDV, C_ANDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
235	{AADDV, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
236
237	{AAND, C_AND0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
238	{AAND, C_AND0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
239	{AAND, C_ADDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
240	{AAND, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
241
242	{AADD, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
243	{AADD, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
244	{AADDV, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
245	{AADDV, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
246	{AAND, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
247	{AAND, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
248
249	{AADD, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
250	{AADDV, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
251	{AAND, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
252	{AADD, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
253	{AADDV, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
254	{AAND, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
255
256	{AADDV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
257	{AADDV, C_DCON, C_REG, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
258
259	{ASLL, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
260	{ASLL, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
261
262	{ASLLV, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
263	{ASLLV, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
264
265	{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
266	{ASYSCALL, C_ANDCON, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
267
268	{ABEQ, C_REG, C_REG, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
269	{ABEQ, C_REG, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
270	{ABLEZ, C_REG, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
271	{ABFPT, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, NOTUSETMP},
272
273	{AJMP, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // b
274	{AJAL, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // bl
275
276	{AJMP, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGZERO, 0}, // jirl r0, rj, 0
277	{AJAL, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGLINK, 0}, // jirl r1, rj, 0
278
279	{AMOVW, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
280	{AMOVF, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
281	{AMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
282	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
283	{AMOVF, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
284	{AMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
285	{AMOVW, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
286	{AMOVF, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
287	{AMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
288
289	{AMOVW, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
290	{AMOVF, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
291	{AMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
292	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
293	{AMOVF, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
294	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
295	{AMOVW, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
296	{AMOVF, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
297	{AMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
298	{AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
299	{AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
300	{AMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
301	{AMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
302
303	{AMOVW, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
304	{AMOVF, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
305	{AMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
306	{AMOVW, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
307	{AMOVF, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
308	{AMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
309	{AMOVW, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
310	{AMOVF, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
311	{AMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
312
313	{AMOVW, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
314	{AMOVF, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
315	{AMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
316	{AMOVW, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
317	{AMOVF, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
318	{AMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
319	{AMOVW, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
320	{AMOVF, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
321	{AMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
322	{AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
323	{AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
324	{AMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
325	{AMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
326
327	{AMOVW, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 30, 4, 0, 0},
328	{AMOVW, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 31, 4, 0, 0},
329	{AMOVV, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 47, 4, 0, 0},
330	{AMOVV, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 48, 4, 0, 0},
331
332	{AMOVV, C_FCCREG, C_NONE, C_NONE, C_REG, C_NONE, 63, 4, 0, 0},
333	{AMOVV, C_REG, C_NONE, C_NONE, C_FCCREG, C_NONE, 64, 4, 0, 0},
334
335	{AMOVW, C_ADDCON, C_NONE, C_NONE, C_FREG, C_NONE, 34, 8, 0, 0},
336	{AMOVW, C_ANDCON, C_NONE, C_NONE, C_FREG, C_NONE, 34, 8, 0, 0},
337
338	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
339	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
340	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
341	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
342	{AMOVWU, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
343
344	{AMOVB, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
345	{AMOVW, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
346	{AMOVV, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
347	{AMOVBU, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
348	{AMOVWU, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
349
350	{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 40, 4, 0, 0},
351	{AWORD, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 61, 4, 0, 0},
352
353	{AMOVV, C_GOTADDR, C_NONE, C_NONE, C_REG, C_NONE, 65, 8, 0, 0},
354
355	{ATEQ, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
356	{ATEQ, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
357
358	{ARDTIMELW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
359	{AAMSWAPW, C_REG, C_NONE, C_NONE, C_ZOREG, C_REG, 66, 4, 0, 0},
360	{ANOOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
361
362	{obj.APCALIGN, C_SCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
363	{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, C_NONE, 0, 0, 0, 0},
364	{obj.APCDATA, C_DCON, C_NONE, C_NONE, C_DCON, C_NONE, 0, 0, 0, 0},
365	{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, C_NONE, 0, 0, 0, 0},
366	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
367	{obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0}, // nop variants, see #40689
368	{obj.ANOP, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0}, // nop variants, see #40689
369	{obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
370	{obj.ANOP, C_FREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
371	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // same as AJMP
372	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // same as AJMP
373
374	{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
375}
376
377var atomicInst = map[obj.As]uint32{
378	AAMSWAPB:   0x070B8 << 15, // amswap.b
379	AAMSWAPH:   0x070B9 << 15, // amswap.h
380	AAMSWAPW:   0x070C0 << 15, // amswap.w
381	AAMSWAPV:   0x070C1 << 15, // amswap.d
382	AAMCASB:    0x070B0 << 15, // amcas.b
383	AAMCASH:    0x070B1 << 15, // amcas.h
384	AAMCASW:    0x070B2 << 15, // amcas.w
385	AAMCASV:    0x070B3 << 15, // amcas.d
386	AAMADDW:    0x070C2 << 15, // amadd.w
387	AAMADDV:    0x070C3 << 15, // amadd.d
388	AAMANDW:    0x070C4 << 15, // amand.w
389	AAMANDV:    0x070C5 << 15, // amand.d
390	AAMORW:     0x070C6 << 15, // amor.w
391	AAMORV:     0x070C7 << 15, // amor.d
392	AAMXORW:    0x070C8 << 15, // amxor.w
393	AAMXORV:    0x070C9 << 15, // amxor.d
394	AAMMAXW:    0x070CA << 15, // ammax.w
395	AAMMAXV:    0x070CB << 15, // ammax.d
396	AAMMINW:    0x070CC << 15, // ammin.w
397	AAMMINV:    0x070CD << 15, // ammin.d
398	AAMMAXWU:   0x070CE << 15, // ammax.wu
399	AAMMAXVU:   0x070CF << 15, // ammax.du
400	AAMMINWU:   0x070D0 << 15, // ammin.wu
401	AAMMINVU:   0x070D1 << 15, // ammin.du
402	AAMSWAPDBB: 0x070BC << 15, // amswap_db.b
403	AAMSWAPDBH: 0x070BD << 15, // amswap_db.h
404	AAMSWAPDBW: 0x070D2 << 15, // amswap_db.w
405	AAMSWAPDBV: 0x070D3 << 15, // amswap_db.d
406	AAMCASDBB:  0x070B4 << 15, // amcas_db.b
407	AAMCASDBH:  0x070B5 << 15, // amcas_db.h
408	AAMCASDBW:  0x070B6 << 15, // amcas_db.w
409	AAMCASDBV:  0x070B7 << 15, // amcas_db.d
410	AAMADDDBW:  0x070D4 << 15, // amadd_db.w
411	AAMADDDBV:  0x070D5 << 15, // amadd_db.d
412	AAMANDDBW:  0x070D6 << 15, // amand_db.w
413	AAMANDDBV:  0x070D7 << 15, // amand_db.d
414	AAMORDBW:   0x070D8 << 15, // amor_db.w
415	AAMORDBV:   0x070D9 << 15, // amor_db.d
416	AAMXORDBW:  0x070DA << 15, // amxor_db.w
417	AAMXORDBV:  0x070DB << 15, // amxor_db.d
418	AAMMAXDBW:  0x070DC << 15, // ammax_db.w
419	AAMMAXDBV:  0x070DD << 15, // ammax_db.d
420	AAMMINDBW:  0x070DE << 15, // ammin_db.w
421	AAMMINDBV:  0x070DF << 15, // ammin_db.d
422	AAMMAXDBWU: 0x070E0 << 15, // ammax_db.wu
423	AAMMAXDBVU: 0x070E1 << 15, // ammax_db.du
424	AAMMINDBWU: 0x070E2 << 15, // ammin_db.wu
425	AAMMINDBVU: 0x070E3 << 15, // ammin_db.du
426}
427
428func IsAtomicInst(as obj.As) bool {
429	_, ok := atomicInst[as]
430
431	return ok
432}
433
434// pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
435// reporting an error if alignedValue is not a power of two or is out of range.
436func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
437	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
438		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
439	}
440	return int(-pc & (alignedValue - 1))
441}
442
443var oprange [ALAST & obj.AMask][]Optab
444
445var xcmp [C_NCLASS][C_NCLASS]bool
446
447func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
448	if ctxt.Retpoline {
449		ctxt.Diag("-spectre=ret not supported on loong64")
450		ctxt.Retpoline = false // don't keep printing
451	}
452
453	p := cursym.Func().Text
454	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
455		return
456	}
457
458	c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.Arch.FixedFrameSize)}
459
460	if oprange[AOR&obj.AMask] == nil {
461		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
462	}
463
464	pc := int64(0)
465	p.Pc = pc
466
467	var m int
468	var o *Optab
469	for p = p.Link; p != nil; p = p.Link {
470		p.Pc = pc
471		o = c.oplook(p)
472		m = int(o.size)
473		if m == 0 {
474			switch p.As {
475			case obj.APCALIGN:
476				alignedValue := p.From.Offset
477				m = pcAlignPadLength(ctxt, pc, alignedValue)
478				// Update the current text symbol alignment value.
479				if int32(alignedValue) > cursym.Func().Align {
480					cursym.Func().Align = int32(alignedValue)
481				}
482				break
483			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
484				continue
485			default:
486				c.ctxt.Diag("zero-width instruction\n%v", p)
487			}
488		}
489
490		pc += int64(m)
491	}
492
493	c.cursym.Size = pc
494
495	// mark loop entry instructions for padding
496	// loop entrances are defined as targets of backward branches
497	for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
498		if q := p.To.Target(); q != nil && q.Pc < p.Pc {
499			q.Mark |= branchLoopHead
500		}
501	}
502
503	// Run these passes until convergence.
504	for {
505		rescan := false
506		pc = 0
507		prev := c.cursym.Func().Text
508		for p = prev.Link; p != nil; prev, p = p, p.Link {
509			p.Pc = pc
510			o = c.oplook(p)
511
512			// Prepend a PCALIGN $loopAlign to each of the loop heads
513			// that need padding, if not already done so (because this
514			// pass may execute more than once).
515			//
516			// This needs to come before any pass that look at pc,
517			// because pc will be adjusted if padding happens.
518			if p.Mark&branchLoopHead != 0 && pc&(loopAlign-1) != 0 &&
519				!(prev.As == obj.APCALIGN && prev.From.Offset >= loopAlign) {
520				q := c.newprog()
521				prev.Link = q
522				q.Link = p
523				q.Pc = pc
524				q.As = obj.APCALIGN
525				q.From.Type = obj.TYPE_CONST
526				q.From.Offset = loopAlign
527				// Don't associate the synthesized PCALIGN with
528				// the original source position, for deterministic
529				// mapping between source and corresponding asm.
530				// q.Pos = p.Pos
531
532				// Manually make the PCALIGN come into effect,
533				// since this loop iteration is for p.
534				pc += int64(pcAlignPadLength(ctxt, pc, loopAlign))
535				p.Pc = pc
536				rescan = true
537			}
538
539			// very large conditional branches
540			//
541			// if any procedure is large enough to generate a large SBRA branch, then
542			// generate extra passes putting branches around jmps to fix. this is rare.
543			if o.type_ == 6 && p.To.Target() != nil {
544				otxt := p.To.Target().Pc - pc
545
546				// On loong64, the immediate value field of the conditional branch instructions
547				// BFPT and BFPT is 21 bits, and the others are 16 bits. The jump target address
548				// is to logically shift the immediate value in the instruction code to the left
549				// by 2 bits and then sign extend.
550				bound := int64(1 << (18 - 1))
551
552				switch p.As {
553				case ABFPT, ABFPF:
554					bound = int64(1 << (23 - 1))
555				}
556
557				if otxt < -bound || otxt >= bound {
558					q := c.newprog()
559					q.Link = p.Link
560					p.Link = q
561					q.As = AJMP
562					q.Pos = p.Pos
563					q.To.Type = obj.TYPE_BRANCH
564					q.To.SetTarget(p.To.Target())
565					p.To.SetTarget(q)
566					q = c.newprog()
567					q.Link = p.Link
568					p.Link = q
569					q.As = AJMP
570					q.Pos = p.Pos
571					q.To.Type = obj.TYPE_BRANCH
572					q.To.SetTarget(q.Link.Link)
573					rescan = true
574				}
575			}
576
577			m = int(o.size)
578			if m == 0 {
579				switch p.As {
580				case obj.APCALIGN:
581					alignedValue := p.From.Offset
582					m = pcAlignPadLength(ctxt, pc, alignedValue)
583					break
584				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
585					continue
586				default:
587					c.ctxt.Diag("zero-width instruction\n%v", p)
588				}
589			}
590
591			pc += int64(m)
592		}
593
594		c.cursym.Size = pc
595
596		if !rescan {
597			break
598		}
599	}
600
601	pc += -pc & (FuncAlign - 1)
602	c.cursym.Size = pc
603
604	// lay out the code, emitting code and data relocations.
605
606	c.cursym.Grow(c.cursym.Size)
607
608	bp := c.cursym.P
609	var i int32
610	var out [5]uint32
611	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
612		c.pc = p.Pc
613		o = c.oplook(p)
614		if int(o.size) > 4*len(out) {
615			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
616		}
617		if p.As == obj.APCALIGN {
618			alignedValue := p.From.Offset
619			v := pcAlignPadLength(c.ctxt, p.Pc, alignedValue)
620			for i = 0; i < int32(v/4); i++ {
621				// emit ANOOP instruction by the padding size
622				c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_12IRR(c.opirr(AAND), 0, 0, 0))
623				bp = bp[4:]
624			}
625			continue
626		}
627		c.asmout(p, o, out[:])
628		for i = 0; i < int32(o.size/4); i++ {
629			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
630			bp = bp[4:]
631		}
632	}
633
634	// Mark nonpreemptible instruction sequences.
635	// We use REGTMP as a scratch register during call injection,
636	// so instruction sequences that use REGTMP are unsafe to
637	// preempt asynchronously.
638	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
639}
640
641// isUnsafePoint returns whether p is an unsafe point.
642func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
643	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
644	// preemption sequence clobbers REGTMP.
645	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
646}
647
648// isRestartable returns whether p is a multi-instruction sequence that,
649// if preempted, can be restarted.
650func (c *ctxt0) isRestartable(p *obj.Prog) bool {
651	if c.isUnsafePoint(p) {
652		return false
653	}
654	// If p is a multi-instruction sequence with uses REGTMP inserted by
655	// the assembler in order to materialize a large constant/offset, we
656	// can restart p (at the start of the instruction sequence), recompute
657	// the content of REGTMP, upon async preemption. Currently, all cases
658	// of assembler-inserted REGTMP fall into this category.
659	// If p doesn't use REGTMP, it can be simply preempted, so we don't
660	// mark it.
661	o := c.oplook(p)
662	return o.size > 4 && o.flag&NOTUSETMP == 0
663}
664
665func isint32(v int64) bool {
666	return int64(int32(v)) == v
667}
668
669func isuint32(v uint64) bool {
670	return uint64(uint32(v)) == v
671}
672
673func (c *ctxt0) aclass(a *obj.Addr) int {
674	switch a.Type {
675	case obj.TYPE_NONE:
676		return C_NONE
677
678	case obj.TYPE_REG:
679		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
680			return C_REG
681		}
682		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
683			return C_FREG
684		}
685		if REG_FCSR0 <= a.Reg && a.Reg <= REG_FCSR31 {
686			return C_FCSRREG
687		}
688		if REG_FCC0 <= a.Reg && a.Reg <= REG_FCC31 {
689			return C_FCCREG
690		}
691		return C_GOK
692
693	case obj.TYPE_MEM:
694		switch a.Name {
695		case obj.NAME_EXTERN,
696			obj.NAME_STATIC:
697			if a.Sym == nil {
698				break
699			}
700			c.instoffset = a.Offset
701			if a.Sym != nil { // use relocation
702				if a.Sym.Type == objabi.STLSBSS {
703					if c.ctxt.Flag_shared {
704						return C_TLS_IE
705					} else {
706						return C_TLS_LE
707					}
708				}
709				return C_ADDR
710			}
711			return C_LEXT
712
713		case obj.NAME_AUTO:
714			if a.Reg == REGSP {
715				// unset base register for better printing, since
716				// a.Offset is still relative to pseudo-SP.
717				a.Reg = obj.REG_NONE
718			}
719			c.instoffset = int64(c.autosize) + a.Offset
720			if c.instoffset >= -BIG && c.instoffset < BIG {
721				return C_SAUTO
722			}
723			return C_LAUTO
724
725		case obj.NAME_PARAM:
726			if a.Reg == REGSP {
727				// unset base register for better printing, since
728				// a.Offset is still relative to pseudo-FP.
729				a.Reg = obj.REG_NONE
730			}
731			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
732			if c.instoffset >= -BIG && c.instoffset < BIG {
733				return C_SAUTO
734			}
735			return C_LAUTO
736
737		case obj.NAME_NONE:
738			c.instoffset = a.Offset
739			if c.instoffset == 0 {
740				return C_ZOREG
741			}
742			if c.instoffset >= -BIG && c.instoffset < BIG {
743				return C_SOREG
744			}
745			return C_LOREG
746
747		case obj.NAME_GOTREF:
748			return C_GOTADDR
749		}
750
751		return C_GOK
752
753	case obj.TYPE_TEXTSIZE:
754		return C_TEXTSIZE
755
756	case obj.TYPE_CONST,
757		obj.TYPE_ADDR:
758		switch a.Name {
759		case obj.NAME_NONE:
760			c.instoffset = a.Offset
761			if a.Reg != 0 {
762				if -BIG <= c.instoffset && c.instoffset <= BIG {
763					return C_SACON
764				}
765				if isint32(c.instoffset) {
766					return C_LACON
767				}
768				return C_DACON
769			}
770
771		case obj.NAME_EXTERN,
772			obj.NAME_STATIC:
773			s := a.Sym
774			if s == nil {
775				return C_GOK
776			}
777
778			c.instoffset = a.Offset
779			if s.Type == objabi.STLSBSS {
780				return C_STCON // address of TLS variable
781			}
782			return C_LECON
783
784		case obj.NAME_AUTO:
785			if a.Reg == REGSP {
786				// unset base register for better printing, since
787				// a.Offset is still relative to pseudo-SP.
788				a.Reg = obj.REG_NONE
789			}
790			c.instoffset = int64(c.autosize) + a.Offset
791			if c.instoffset >= -BIG && c.instoffset < BIG {
792				return C_SACON
793			}
794			return C_LACON
795
796		case obj.NAME_PARAM:
797			if a.Reg == REGSP {
798				// unset base register for better printing, since
799				// a.Offset is still relative to pseudo-FP.
800				a.Reg = obj.REG_NONE
801			}
802			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
803			if c.instoffset >= -BIG && c.instoffset < BIG {
804				return C_SACON
805			}
806			return C_LACON
807
808		default:
809			return C_GOK
810		}
811
812		if c.instoffset != int64(int32(c.instoffset)) {
813			return C_DCON
814		}
815
816		if c.instoffset >= 0 {
817			if c.instoffset == 0 {
818				return C_ZCON
819			}
820			if c.instoffset <= 0x7ff {
821				return C_SCON
822			}
823			if c.instoffset <= 0xfff {
824				return C_ANDCON
825			}
826			if c.instoffset&0xfff == 0 && isuint32(uint64(c.instoffset)) { // && ((instoffset & (1<<31)) == 0)
827				return C_UCON
828			}
829			if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
830				return C_LCON
831			}
832			return C_LCON
833		}
834
835		if c.instoffset >= -0x800 {
836			return C_ADDCON
837		}
838		if c.instoffset&0xfff == 0 && isint32(c.instoffset) {
839			return C_UCON
840		}
841		if isint32(c.instoffset) {
842			return C_LCON
843		}
844		return C_LCON
845
846	case obj.TYPE_BRANCH:
847		return C_SBRA
848	}
849
850	return C_GOK
851}
852
853func prasm(p *obj.Prog) {
854	fmt.Printf("%v\n", p)
855}
856
857func (c *ctxt0) oplook(p *obj.Prog) *Optab {
858	if oprange[AOR&obj.AMask] == nil {
859		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
860	}
861
862	a1 := int(p.Optab)
863	if a1 != 0 {
864		return &optab[a1-1]
865	}
866
867	// first source operand
868	a1 = int(p.From.Class)
869	if a1 == 0 {
870		a1 = c.aclass(&p.From) + 1
871		p.From.Class = int8(a1)
872	}
873	a1--
874
875	// first destination operand
876	a4 := int(p.To.Class)
877	if a4 == 0 {
878		a4 = c.aclass(&p.To) + 1
879		p.To.Class = int8(a4)
880	}
881	a4--
882
883	// 2nd source operand
884	a2 := C_NONE
885	if p.Reg != 0 {
886		a2 = C_REG
887	}
888
889	// 2nd destination operand
890	a5 := C_NONE
891	if p.RegTo2 != 0 {
892		a5 = C_REG
893	}
894
895	// 3rd source operand
896	a3 := C_NONE
897	if len(p.RestArgs) > 0 {
898		a3 = int(p.RestArgs[0].Class)
899		if a3 == 0 {
900			a3 = c.aclass(&p.RestArgs[0].Addr) + 1
901			p.RestArgs[0].Class = int8(a3)
902		}
903		a3--
904	}
905
906	ops := oprange[p.As&obj.AMask]
907	c1 := &xcmp[a1]
908	c4 := &xcmp[a4]
909	for i := range ops {
910		op := &ops[i]
911		if (int(op.reg) == a2) && int(op.from3) == a3 && c1[op.from1] && c4[op.to1] && (int(op.to2) == a5) {
912			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
913			return op
914		}
915	}
916
917	c.ctxt.Diag("illegal combination %v %v %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), DRconv(a5))
918	prasm(p)
919	// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
920	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0}
921}
922
923func cmp(a int, b int) bool {
924	if a == b {
925		return true
926	}
927	switch a {
928	case C_DCON:
929		if b == C_LCON {
930			return true
931		}
932		fallthrough
933	case C_LCON:
934		if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
935			return true
936		}
937
938	case C_ADD0CON:
939		if b == C_ADDCON {
940			return true
941		}
942		fallthrough
943
944	case C_ADDCON:
945		if b == C_ZCON || b == C_SCON {
946			return true
947		}
948
949	case C_AND0CON:
950		if b == C_ANDCON {
951			return true
952		}
953		fallthrough
954
955	case C_ANDCON:
956		if b == C_ZCON || b == C_SCON {
957			return true
958		}
959
960	case C_UCON:
961		if b == C_ZCON {
962			return true
963		}
964
965	case C_SCON:
966		if b == C_ZCON {
967			return true
968		}
969
970	case C_LACON:
971		if b == C_SACON {
972			return true
973		}
974
975	case C_LBRA:
976		if b == C_SBRA {
977			return true
978		}
979
980	case C_LEXT:
981		if b == C_SEXT {
982			return true
983		}
984
985	case C_LAUTO:
986		if b == C_SAUTO {
987			return true
988		}
989
990	case C_REG:
991		if b == C_ZCON {
992			return true
993		}
994
995	case C_LOREG:
996		if b == C_ZOREG || b == C_SOREG {
997			return true
998		}
999
1000	case C_SOREG:
1001		if b == C_ZOREG {
1002			return true
1003		}
1004	}
1005
1006	return false
1007}
1008
1009type ocmp []Optab
1010
1011func (x ocmp) Len() int {
1012	return len(x)
1013}
1014
1015func (x ocmp) Swap(i, j int) {
1016	x[i], x[j] = x[j], x[i]
1017}
1018
1019func (x ocmp) Less(i, j int) bool {
1020	p1 := &x[i]
1021	p2 := &x[j]
1022	n := int(p1.as) - int(p2.as)
1023	if n != 0 {
1024		return n < 0
1025	}
1026	n = int(p1.from1) - int(p2.from1)
1027	if n != 0 {
1028		return n < 0
1029	}
1030	n = int(p1.reg) - int(p2.reg)
1031	if n != 0 {
1032		return n < 0
1033	}
1034	n = int(p1.to1) - int(p2.to1)
1035	if n != 0 {
1036		return n < 0
1037	}
1038	return false
1039}
1040
1041func opset(a, b0 obj.As) {
1042	oprange[a&obj.AMask] = oprange[b0]
1043}
1044
1045func buildop(ctxt *obj.Link) {
1046	if ctxt.DiagFunc == nil {
1047		ctxt.DiagFunc = func(format string, args ...interface{}) {
1048			log.Printf(format, args...)
1049		}
1050	}
1051
1052	if oprange[AOR&obj.AMask] != nil {
1053		// Already initialized; stop now.
1054		// This happens in the cmd/asm tests,
1055		// each of which re-initializes the arch.
1056		return
1057	}
1058
1059	var n int
1060
1061	for i := 0; i < C_NCLASS; i++ {
1062		for n = 0; n < C_NCLASS; n++ {
1063			if cmp(n, i) {
1064				xcmp[i][n] = true
1065			}
1066		}
1067	}
1068	for n = 0; optab[n].as != obj.AXXX; n++ {
1069	}
1070	sort.Sort(ocmp(optab[:n]))
1071	for i := 0; i < n; i++ {
1072		r := optab[i].as
1073		r0 := r & obj.AMask
1074		start := i
1075		for optab[i].as == r {
1076			i++
1077		}
1078		oprange[r0] = optab[start:i]
1079		i--
1080
1081		switch r {
1082		default:
1083			ctxt.Diag("unknown op in build: %v", r)
1084			ctxt.DiagFlush()
1085			log.Fatalf("bad code")
1086
1087		case AABSF:
1088			opset(AMOVFD, r0)
1089			opset(AMOVDF, r0)
1090			opset(AMOVWF, r0)
1091			opset(AMOVFW, r0)
1092			opset(AMOVWD, r0)
1093			opset(AMOVDW, r0)
1094			opset(ANEGF, r0)
1095			opset(ANEGD, r0)
1096			opset(AABSD, r0)
1097			opset(ATRUNCDW, r0)
1098			opset(ATRUNCFW, r0)
1099			opset(ASQRTF, r0)
1100			opset(ASQRTD, r0)
1101
1102		case AMOVVF:
1103			opset(AMOVVD, r0)
1104			opset(AMOVFV, r0)
1105			opset(AMOVDV, r0)
1106			opset(ATRUNCDV, r0)
1107			opset(ATRUNCFV, r0)
1108
1109		case AADD:
1110			opset(ASGT, r0)
1111			opset(ASGTU, r0)
1112			opset(AADDU, r0)
1113
1114		case AADDV:
1115			opset(AADDVU, r0)
1116
1117		case AADDF:
1118			opset(ADIVF, r0)
1119			opset(ADIVD, r0)
1120			opset(AMULF, r0)
1121			opset(AMULD, r0)
1122			opset(ASUBF, r0)
1123			opset(ASUBD, r0)
1124			opset(AADDD, r0)
1125
1126		case AAND:
1127			opset(AOR, r0)
1128			opset(AXOR, r0)
1129
1130		case ABEQ:
1131			opset(ABNE, r0)
1132			opset(ABLT, r0)
1133			opset(ABGE, r0)
1134			opset(ABGEU, r0)
1135			opset(ABLTU, r0)
1136
1137		case ABLEZ:
1138			opset(ABGEZ, r0)
1139			opset(ABLTZ, r0)
1140			opset(ABGTZ, r0)
1141
1142		case AMOVB:
1143			opset(AMOVH, r0)
1144
1145		case AMOVBU:
1146			opset(AMOVHU, r0)
1147
1148		case AMUL:
1149			opset(AMULU, r0)
1150			opset(AMULH, r0)
1151			opset(AMULHU, r0)
1152			opset(AREM, r0)
1153			opset(AREMU, r0)
1154			opset(ADIV, r0)
1155			opset(ADIVU, r0)
1156
1157		case AMULV:
1158			opset(AMULVU, r0)
1159			opset(AMULHV, r0)
1160			opset(AMULHVU, r0)
1161			opset(AREMV, r0)
1162			opset(AREMVU, r0)
1163			opset(ADIVV, r0)
1164			opset(ADIVVU, r0)
1165
1166		case ASLL:
1167			opset(ASRL, r0)
1168			opset(ASRA, r0)
1169			opset(AROTR, r0)
1170
1171		case ASLLV:
1172			opset(ASRAV, r0)
1173			opset(ASRLV, r0)
1174			opset(AROTRV, r0)
1175
1176		case ASUB:
1177			opset(ASUBU, r0)
1178			opset(ANOR, r0)
1179
1180		case ASUBV:
1181			opset(ASUBVU, r0)
1182
1183		case ASYSCALL:
1184			opset(ADBAR, r0)
1185			opset(ABREAK, r0)
1186
1187		case ACMPEQF:
1188			opset(ACMPGTF, r0)
1189			opset(ACMPGTD, r0)
1190			opset(ACMPGEF, r0)
1191			opset(ACMPGED, r0)
1192			opset(ACMPEQD, r0)
1193
1194		case ABFPT:
1195			opset(ABFPF, r0)
1196
1197		case AMOVWL:
1198			opset(AMOVWR, r0)
1199
1200		case AMOVVL:
1201			opset(AMOVVR, r0)
1202
1203		case AMOVW,
1204			AMOVD,
1205			AMOVF,
1206			AMOVV,
1207			ARFE,
1208			AJAL,
1209			AJMP,
1210			AMOVWU,
1211			ALL,
1212			ALLV,
1213			ASC,
1214			ASCV,
1215			ANEGW,
1216			ANEGV,
1217			AWORD,
1218			obj.ANOP,
1219			obj.ATEXT,
1220			obj.AFUNCDATA,
1221			obj.APCALIGN,
1222			obj.APCDATA,
1223			obj.ADUFFZERO,
1224			obj.ADUFFCOPY:
1225			break
1226
1227		case ARDTIMELW:
1228			opset(ARDTIMEHW, r0)
1229			opset(ARDTIMED, r0)
1230
1231		case ACLO:
1232			opset(ACLZ, r0)
1233
1234		case ATEQ:
1235			opset(ATNE, r0)
1236
1237		case AMASKEQZ:
1238			opset(AMASKNEZ, r0)
1239
1240		case ANOOP:
1241			opset(obj.AUNDEF, r0)
1242
1243		case AAMSWAPW:
1244			for i := range atomicInst {
1245				if i == AAMSWAPW {
1246					continue
1247				}
1248				opset(i, r0)
1249			}
1250		}
1251	}
1252}
1253
1254func OP(x uint32, y uint32) uint32 {
1255	return x<<3 | y<<0
1256}
1257
1258func SP(x uint32, y uint32) uint32 {
1259	return x<<29 | y<<26
1260}
1261
1262func OP_TEN(x uint32, y uint32) uint32 {
1263	return x<<21 | y<<10
1264}
1265
1266// r1 -> rk
1267// r2 -> rj
1268// r3 -> rd
1269func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1270	return op | (r1&0x1F)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
1271}
1272
1273// r2 -> rj
1274// r3 -> rd
1275func OP_RR(op uint32, r2 uint32, r3 uint32) uint32 {
1276	return op | (r2&0x1F)<<5 | (r3&0x1F)<<0
1277}
1278
1279func OP_16IR_5I(op uint32, i uint32, r2 uint32) uint32 {
1280	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | ((i >> 16) & 0x1F)
1281}
1282
1283func OP_16IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
1284	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
1285}
1286
1287func OP_12IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
1288	return op | (i&0xFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
1289}
1290
1291func OP_IR(op uint32, i uint32, r2 uint32) uint32 {
1292	return op | (i&0xFFFFF)<<5 | (r2&0x1F)<<0 // ui20, rd5
1293}
1294
1295func OP_15I(op uint32, i uint32) uint32 {
1296	return op | (i&0x7FFF)<<0
1297}
1298
1299// Encoding for the 'b' or 'bl' instruction.
1300func OP_B_BL(op uint32, i uint32) uint32 {
1301	return op | ((i & 0xFFFF) << 10) | ((i >> 16) & 0x3FF)
1302}
1303
1304func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1305	o1 := uint32(0)
1306	o2 := uint32(0)
1307	o3 := uint32(0)
1308	o4 := uint32(0)
1309	o5 := uint32(0)
1310
1311	add := AADDU
1312	add = AADDVU
1313
1314	switch o.type_ {
1315	default:
1316		c.ctxt.Diag("unknown type %d %v", o.type_)
1317		prasm(p)
1318
1319	case 0: // pseudo ops
1320		break
1321
1322	case 1: // mov r1,r2 ==> OR r1,r0,r2
1323		a := AOR
1324		if p.As == AMOVW {
1325			a = ASLL
1326		}
1327		o1 = OP_RRR(c.oprrr(a), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
1328
1329	case 2: // add/sub r1,[r2],r3
1330		r := int(p.Reg)
1331		if p.As == ANEGW || p.As == ANEGV {
1332			r = REGZERO
1333		}
1334		if r == 0 {
1335			r = int(p.To.Reg)
1336		}
1337		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1338
1339	case 3: // mov $soreg, r ==> or/add $i,o,r
1340		v := c.regoff(&p.From)
1341
1342		r := int(p.From.Reg)
1343		if r == 0 {
1344			r = int(o.param)
1345		}
1346		a := add
1347		if o.from1 == C_ANDCON {
1348			a = AOR
1349		}
1350
1351		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1352
1353	case 4: // add $scon,[r1],r2
1354		v := c.regoff(&p.From)
1355
1356		r := int(p.Reg)
1357		if r == 0 {
1358			r = int(p.To.Reg)
1359		}
1360
1361		o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1362
1363	case 5: // syscall
1364		v := c.regoff(&p.From)
1365		o1 = OP_15I(c.opi(p.As), uint32(v))
1366
1367	case 6: // beq r1,[r2],sbra
1368		v := int32(0)
1369		if p.To.Target() != nil {
1370			v = int32(p.To.Target().Pc-p.Pc) >> 2
1371		}
1372		as, rd, rj, width := p.As, p.Reg, p.From.Reg, 16
1373		switch as {
1374		case ABGTZ, ABLEZ:
1375			rd, rj = rj, rd
1376		case ABFPT, ABFPF:
1377			width = 21
1378			// FCC0 is the implicit source operand, now that we
1379			// don't register-allocate from the FCC bank.
1380			rd = REG_FCC0
1381		case ABEQ, ABNE:
1382			if rd == 0 || rd == REGZERO || rj == REGZERO {
1383				// BEQZ/BNEZ can be encoded with 21-bit offsets.
1384				width = 21
1385				as = -as
1386				if rj == 0 || rj == REGZERO {
1387					rj = rd
1388				}
1389			}
1390		}
1391		switch width {
1392		case 21:
1393			if (v<<11)>>11 != v {
1394				c.ctxt.Diag("21 bit-width, short branch too far\n%v", p)
1395			}
1396			o1 = OP_16IR_5I(c.opirr(as), uint32(v), uint32(rj))
1397		case 16:
1398			if (v<<16)>>16 != v {
1399				c.ctxt.Diag("16 bit-width, short branch too far\n%v", p)
1400			}
1401			o1 = OP_16IRR(c.opirr(as), uint32(v), uint32(rj), uint32(rd))
1402		default:
1403			c.ctxt.Diag("unexpected branch encoding\n%v", p)
1404		}
1405
1406	case 7: // mov r, soreg
1407		r := int(p.To.Reg)
1408		if r == 0 {
1409			r = int(o.param)
1410		}
1411		v := c.regoff(&p.To)
1412		o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1413
1414	case 8: // mov soreg, r
1415		r := int(p.From.Reg)
1416		if r == 0 {
1417			r = int(o.param)
1418		}
1419		v := c.regoff(&p.From)
1420		o1 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1421
1422	case 9: // sll r1,[r2],r3
1423		if p.As != ACLO && p.As != ACLZ {
1424			r := int(p.Reg)
1425			if r == 0 {
1426				r = int(p.To.Reg)
1427			}
1428			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1429		} else { // clo r1,r2
1430			o1 = OP_RR(c.oprr(p.As), uint32(p.From.Reg), uint32(p.To.Reg))
1431		}
1432
1433	case 10: // add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2
1434		v := c.regoff(&p.From)
1435		a := AOR
1436		if v < 0 {
1437			a = AADDU
1438		}
1439		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1440		r := int(p.Reg)
1441		if r == 0 {
1442			r = int(p.To.Reg)
1443		}
1444		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1445
1446	case 11: // jmp lbra
1447		v := int32(0)
1448		if p.To.Target() != nil {
1449			v = int32(p.To.Target().Pc-p.Pc) >> 2
1450		}
1451		o1 = OP_B_BL(c.opirr(p.As), uint32(v))
1452		if p.To.Sym == nil {
1453			if p.As == AJMP {
1454				break
1455			}
1456			p.To.Sym = c.cursym.Func().Text.From.Sym
1457			p.To.Offset = p.To.Target().Pc
1458		}
1459		rel := obj.Addrel(c.cursym)
1460		rel.Off = int32(c.pc)
1461		rel.Siz = 4
1462		rel.Sym = p.To.Sym
1463		rel.Add = p.To.Offset
1464		rel.Type = objabi.R_CALLLOONG64
1465
1466	case 12: // movbs r,r
1467		// NOTE: this case does not use REGTMP. If it ever does,
1468		// remove the NOTUSETMP flag in optab.
1469		v := 16
1470		if p.As == AMOVB {
1471			v = 24
1472		}
1473		o1 = OP_16IRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
1474		o2 = OP_16IRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1475
1476	case 13: // movbu r,r
1477		if p.As == AMOVBU {
1478			o1 = OP_12IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1479		} else {
1480			// bstrpick.d (msbd=15, lsbd=0)
1481			o1 = (0x33c0 << 10) | ((uint32(p.From.Reg) & 0x1f) << 5) | (uint32(p.To.Reg) & 0x1F)
1482		}
1483
1484	case 14: // movwu r,r
1485		// NOTE: this case does not use REGTMP. If it ever does,
1486		// remove the NOTUSETMP flag in optab.
1487		o1 = OP_16IRR(c.opirr(-ASLLV), uint32(32)&0x3f, uint32(p.From.Reg), uint32(p.To.Reg))
1488		o2 = OP_16IRR(c.opirr(-ASRLV), uint32(32)&0x3f, uint32(p.To.Reg), uint32(p.To.Reg))
1489
1490	case 15: // teq $c r,r
1491		v := c.regoff(&p.From)
1492		r := int(p.Reg)
1493		if r == 0 {
1494			r = REGZERO
1495		}
1496		/*
1497			teq c, r1, r2
1498			fallthrough
1499			==>
1500			bne r1, r2, 2
1501			break c
1502			fallthrough
1503		*/
1504		if p.As == ATEQ {
1505			o1 = OP_16IRR(c.opirr(ABNE), uint32(2), uint32(r), uint32(p.To.Reg))
1506		} else { // ATNE
1507			o1 = OP_16IRR(c.opirr(ABEQ), uint32(2), uint32(r), uint32(p.To.Reg))
1508		}
1509		o2 = OP_15I(c.opi(ABREAK), uint32(v))
1510
1511	case 16: // sll $c,[r1],r2
1512		v := c.regoff(&p.From)
1513		r := int(p.Reg)
1514		if r == 0 {
1515			r = int(p.To.Reg)
1516		}
1517
1518		// instruction ending with V:6-digit immediate, others:5-digit immediate
1519		if v >= 32 && vshift(p.As) {
1520			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x3f, uint32(r), uint32(p.To.Reg))
1521		} else {
1522			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x1f, uint32(r), uint32(p.To.Reg))
1523		}
1524
1525	case 17:
1526		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
1527
1528	case 18: // jmp [r1],0(r2)
1529		r := int(p.Reg)
1530		if r == 0 {
1531			r = int(o.param)
1532		}
1533		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
1534		if p.As == obj.ACALL {
1535			rel := obj.Addrel(c.cursym)
1536			rel.Off = int32(c.pc)
1537			rel.Siz = 0
1538			rel.Type = objabi.R_CALLIND
1539		}
1540
1541	case 19: // mov $lcon,r
1542		// NOTE: this case does not use REGTMP. If it ever does,
1543		// remove the NOTUSETMP flag in optab.
1544		v := c.regoff(&p.From)
1545		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
1546		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1547
1548	case 23: // add $lcon,r1,r2
1549		v := c.regoff(&p.From)
1550		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
1551		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1552		r := int(p.Reg)
1553		if r == 0 {
1554			r = int(p.To.Reg)
1555		}
1556		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1557
1558	case 24: // mov $ucon,r
1559		v := c.regoff(&p.From)
1560		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
1561
1562	case 25: // add/and $ucon,[r1],r2
1563		v := c.regoff(&p.From)
1564		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
1565		r := int(p.Reg)
1566		if r == 0 {
1567			r = int(p.To.Reg)
1568		}
1569		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1570
1571	case 26: // mov $lsext/auto/oreg,r
1572		v := c.regoff(&p.From)
1573		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
1574		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1575		r := int(p.From.Reg)
1576		if r == 0 {
1577			r = int(o.param)
1578		}
1579		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1580
1581	case 27: // mov [sl]ext/auto/oreg,fr
1582		v := c.regoff(&p.From)
1583		r := int(p.From.Reg)
1584		if r == 0 {
1585			r = int(o.param)
1586		}
1587		a := -AMOVF
1588		if p.As == AMOVD {
1589			a = -AMOVD
1590		}
1591		switch o.size {
1592		case 12:
1593			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
1594			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1595			o3 = OP_12IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1596
1597		case 4:
1598			o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1599		}
1600
1601	case 28: // mov fr,[sl]ext/auto/oreg
1602		v := c.regoff(&p.To)
1603		r := int(p.To.Reg)
1604		if r == 0 {
1605			r = int(o.param)
1606		}
1607		a := AMOVF
1608		if p.As == AMOVD {
1609			a = AMOVD
1610		}
1611		switch o.size {
1612		case 12:
1613			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
1614			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1615			o3 = OP_12IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1616
1617		case 4:
1618			o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
1619		}
1620
1621	case 30: // movw r,fr
1622		a := OP_TEN(8, 1321) // movgr2fr.w
1623		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1624
1625	case 31: // movw fr,r
1626		a := OP_TEN(8, 1325) // movfr2gr.s
1627		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1628
1629	case 32: // fadd fr1,[fr2],fr3
1630		r := int(p.Reg)
1631		if r == 0 {
1632			r = int(p.To.Reg)
1633		}
1634		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1635
1636	case 33: // fabs fr1, fr3
1637		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1638
1639	case 34: // mov $con,fr
1640		v := c.regoff(&p.From)
1641		a := AADDU
1642		if o.from1 == C_ANDCON {
1643			a = AOR
1644		}
1645		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1646		o2 = OP_RR(OP_TEN(8, 1321), uint32(REGTMP), uint32(p.To.Reg)) // movgr2fr.w
1647
1648	case 35: // mov r,lext/auto/oreg
1649		v := c.regoff(&p.To)
1650		r := int(p.To.Reg)
1651		if r == 0 {
1652			r = int(o.param)
1653		}
1654		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
1655		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1656		o3 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1657
1658	case 36: // mov lext/auto/oreg,r
1659		v := c.regoff(&p.From)
1660		r := int(p.From.Reg)
1661		if r == 0 {
1662			r = int(o.param)
1663		}
1664		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
1665		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1666		o3 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1667
1668	case 40: // word
1669		o1 = uint32(c.regoff(&p.From))
1670
1671	case 47: // movv r,fr
1672		a := OP_TEN(8, 1322) // movgr2fr.d
1673		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1674
1675	case 48: // movv fr,r
1676		a := OP_TEN(8, 1326) // movfr2gr.d
1677		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1678
1679	case 49:
1680		if p.As == ANOOP {
1681			// andi r0, r0, 0
1682			o1 = OP_12IRR(c.opirr(AAND), 0, 0, 0)
1683		} else {
1684			// undef
1685			o1 = OP_15I(c.opi(ABREAK), 0)
1686		}
1687	// relocation operations
1688	case 50: // mov r,addr ==> pcalau12i + sw
1689		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
1690		rel := obj.Addrel(c.cursym)
1691		rel.Off = int32(c.pc)
1692		rel.Siz = 4
1693		rel.Sym = p.To.Sym
1694		rel.Add = p.To.Offset
1695		rel.Type = objabi.R_LOONG64_ADDR_HI
1696
1697		o2 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1698		rel2 := obj.Addrel(c.cursym)
1699		rel2.Off = int32(c.pc + 4)
1700		rel2.Siz = 4
1701		rel2.Sym = p.To.Sym
1702		rel2.Add = p.To.Offset
1703		rel2.Type = objabi.R_LOONG64_ADDR_LO
1704
1705	case 51: // mov addr,r ==> pcalau12i + lw
1706		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
1707		rel := obj.Addrel(c.cursym)
1708		rel.Off = int32(c.pc)
1709		rel.Siz = 4
1710		rel.Sym = p.From.Sym
1711		rel.Add = p.From.Offset
1712		rel.Type = objabi.R_LOONG64_ADDR_HI
1713		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1714		rel2 := obj.Addrel(c.cursym)
1715		rel2.Off = int32(c.pc + 4)
1716		rel2.Siz = 4
1717		rel2.Sym = p.From.Sym
1718		rel2.Add = p.From.Offset
1719		rel2.Type = objabi.R_LOONG64_ADDR_LO
1720
1721	case 52: // mov $lext, r
1722		// NOTE: this case does not use REGTMP. If it ever does,
1723		// remove the NOTUSETMP flag in optab.
1724		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
1725		rel := obj.Addrel(c.cursym)
1726		rel.Off = int32(c.pc)
1727		rel.Siz = 4
1728		rel.Sym = p.From.Sym
1729		rel.Add = p.From.Offset
1730		rel.Type = objabi.R_LOONG64_ADDR_HI
1731		o2 = OP_12IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1732		rel2 := obj.Addrel(c.cursym)
1733		rel2.Off = int32(c.pc + 4)
1734		rel2.Siz = 4
1735		rel2.Sym = p.From.Sym
1736		rel2.Add = p.From.Offset
1737		rel2.Type = objabi.R_LOONG64_ADDR_LO
1738
1739	case 53: // mov r, tlsvar ==>  lu12i.w + ori + add r2, regtmp + sw o(regtmp)
1740		// NOTE: this case does not use REGTMP. If it ever does,
1741		// remove the NOTUSETMP flag in optab.
1742		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
1743		rel := obj.Addrel(c.cursym)
1744		rel.Off = int32(c.pc)
1745		rel.Siz = 4
1746		rel.Sym = p.To.Sym
1747		rel.Add = p.To.Offset
1748		rel.Type = objabi.R_LOONG64_TLS_LE_HI
1749		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
1750		rel2 := obj.Addrel(c.cursym)
1751		rel2.Off = int32(c.pc + 4)
1752		rel2.Siz = 4
1753		rel2.Sym = p.To.Sym
1754		rel2.Add = p.To.Offset
1755		rel2.Type = objabi.R_LOONG64_TLS_LE_LO
1756		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
1757		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1758
1759	case 54: // lu12i.w + ori + add r2, regtmp + lw o(regtmp)
1760		// NOTE: this case does not use REGTMP. If it ever does,
1761		// remove the NOTUSETMP flag in optab.
1762		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
1763		rel := obj.Addrel(c.cursym)
1764		rel.Off = int32(c.pc)
1765		rel.Siz = 4
1766		rel.Sym = p.From.Sym
1767		rel.Add = p.From.Offset
1768		rel.Type = objabi.R_LOONG64_TLS_LE_HI
1769		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
1770		rel2 := obj.Addrel(c.cursym)
1771		rel2.Off = int32(c.pc + 4)
1772		rel2.Siz = 4
1773		rel2.Sym = p.From.Sym
1774		rel2.Add = p.From.Offset
1775		rel2.Type = objabi.R_LOONG64_TLS_LE_LO
1776		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
1777		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1778
1779	case 55: //  lu12i.w + ori + add r2, regtmp
1780		// NOTE: this case does not use REGTMP. If it ever does,
1781		// remove the NOTUSETMP flag in optab.
1782		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
1783		rel := obj.Addrel(c.cursym)
1784		rel.Off = int32(c.pc)
1785		rel.Siz = 4
1786		rel.Sym = p.From.Sym
1787		rel.Add = p.From.Offset
1788		rel.Type = objabi.R_LOONG64_TLS_LE_HI
1789		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
1790		rel2 := obj.Addrel(c.cursym)
1791		rel2.Off = int32(c.pc + 4)
1792		rel2.Siz = 4
1793		rel2.Sym = p.From.Sym
1794		rel2.Add = p.From.Offset
1795		rel2.Type = objabi.R_LOONG64_TLS_LE_LO
1796		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(p.To.Reg))
1797
1798	case 56: // mov r, tlsvar IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + st.d
1799		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
1800		rel := obj.Addrel(c.cursym)
1801		rel.Off = int32(c.pc)
1802		rel.Siz = 4
1803		rel.Sym = p.To.Sym
1804		rel.Add = 0x0
1805		rel.Type = objabi.R_LOONG64_TLS_IE_HI
1806		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
1807		rel2 := obj.Addrel(c.cursym)
1808		rel2.Off = int32(c.pc + 4)
1809		rel2.Siz = 4
1810		rel2.Sym = p.To.Sym
1811		rel2.Add = 0x0
1812		rel2.Type = objabi.R_LOONG64_TLS_IE_LO
1813		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
1814		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1815
1816	case 57: // mov tlsvar, r IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + ld.d
1817		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
1818		rel := obj.Addrel(c.cursym)
1819		rel.Off = int32(c.pc)
1820		rel.Siz = 4
1821		rel.Sym = p.From.Sym
1822		rel.Add = 0x0
1823		rel.Type = objabi.R_LOONG64_TLS_IE_HI
1824		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
1825		rel2 := obj.Addrel(c.cursym)
1826		rel2.Off = int32(c.pc + 4)
1827		rel2.Siz = 4
1828		rel2.Sym = p.From.Sym
1829		rel2.Add = 0x0
1830		rel2.Type = objabi.R_LOONG64_TLS_IE_LO
1831		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
1832		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1833
1834	case 59: // mov $dcon,r
1835		// NOTE: this case does not use REGTMP. If it ever does,
1836		// remove the NOTUSETMP flag in optab.
1837		v := c.vregoff(&p.From)
1838		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
1839		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1840		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
1841		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
1842
1843	case 60: // add $dcon,r1,r2
1844		v := c.vregoff(&p.From)
1845		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
1846		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1847		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
1848		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
1849		r := int(p.Reg)
1850		if r == 0 {
1851			r = int(p.To.Reg)
1852		}
1853		o5 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1854
1855	case 61: // word C_DCON
1856		o1 = uint32(c.vregoff(&p.From))
1857		o2 = uint32(c.vregoff(&p.From) >> 32)
1858
1859	case 62: // rdtimex rd, rj
1860		o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
1861
1862	case 63: // movv c_fcc0, c_reg ==> movcf2gr rd, cj
1863		a := OP_TEN(8, 1335)
1864		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1865
1866	case 64: // movv c_reg, c_fcc0 ==> movgr2cf cd, rj
1867		a := OP_TEN(8, 1334)
1868		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
1869
1870	case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
1871		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
1872		rel := obj.Addrel(c.cursym)
1873		rel.Off = int32(c.pc)
1874		rel.Siz = 4
1875		rel.Sym = p.From.Sym
1876		rel.Type = objabi.R_LOONG64_GOT_HI
1877		rel.Add = 0x0
1878		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1879		rel2 := obj.Addrel(c.cursym)
1880		rel2.Off = int32(c.pc + 4)
1881		rel2.Siz = 4
1882		rel2.Sym = p.From.Sym
1883		rel2.Type = objabi.R_LOONG64_GOT_LO
1884		rel2.Add = 0x0
1885
1886	case 66: // am* From, To, RegTo2 ==> am* RegTo2, From, To
1887		rk := p.From.Reg
1888		rj := p.To.Reg
1889		rd := p.RegTo2
1890
1891		// See section 2.2.7.1 of https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
1892		// for the register usage constraints.
1893		if rd == rj || rd == rk {
1894			c.ctxt.Diag("illegal register combination: %v\n", p)
1895		}
1896		o1 = OP_RRR(atomicInst[p.As], uint32(rk), uint32(rj), uint32(rd))
1897	}
1898
1899	out[0] = o1
1900	out[1] = o2
1901	out[2] = o3
1902	out[3] = o4
1903	out[4] = o5
1904}
1905
1906func (c *ctxt0) vregoff(a *obj.Addr) int64 {
1907	c.instoffset = 0
1908	c.aclass(a)
1909	return c.instoffset
1910}
1911
1912func (c *ctxt0) regoff(a *obj.Addr) int32 {
1913	return int32(c.vregoff(a))
1914}
1915
1916func (c *ctxt0) oprrr(a obj.As) uint32 {
1917	switch a {
1918	case AADD:
1919		return 0x20 << 15
1920	case AADDU:
1921		return 0x20 << 15
1922	case ASGT:
1923		return 0x24 << 15 // SLT
1924	case ASGTU:
1925		return 0x25 << 15 // SLTU
1926	case AMASKEQZ:
1927		return 0x26 << 15
1928	case AMASKNEZ:
1929		return 0x27 << 15
1930	case AAND:
1931		return 0x29 << 15
1932	case AOR:
1933		return 0x2a << 15
1934	case AXOR:
1935		return 0x2b << 15
1936	case ASUB:
1937		return 0x22 << 15
1938	case ASUBU, ANEGW:
1939		return 0x22 << 15
1940	case ANOR:
1941		return 0x28 << 15
1942	case ASLL:
1943		return 0x2e << 15
1944	case ASRL:
1945		return 0x2f << 15
1946	case ASRA:
1947		return 0x30 << 15
1948	case AROTR:
1949		return 0x36 << 15
1950	case ASLLV:
1951		return 0x31 << 15
1952	case ASRLV:
1953		return 0x32 << 15
1954	case ASRAV:
1955		return 0x33 << 15
1956	case AROTRV:
1957		return 0x37 << 15
1958	case AADDV:
1959		return 0x21 << 15
1960	case AADDVU:
1961		return 0x21 << 15
1962	case ASUBV:
1963		return 0x23 << 15
1964	case ASUBVU, ANEGV:
1965		return 0x23 << 15
1966
1967	case AMUL:
1968		return 0x38 << 15 // mul.w
1969	case AMULU:
1970		return 0x38 << 15 // mul.w
1971	case AMULH:
1972		return 0x39 << 15 // mulh.w
1973	case AMULHU:
1974		return 0x3a << 15 // mulhu.w
1975	case AMULV:
1976		return 0x3b << 15 // mul.d
1977	case AMULVU:
1978		return 0x3b << 15 // mul.d
1979	case AMULHV:
1980		return 0x3c << 15 // mulh.d
1981	case AMULHVU:
1982		return 0x3d << 15 // mulhu.d
1983	case ADIV:
1984		return 0x40 << 15 // div.w
1985	case ADIVU:
1986		return 0x42 << 15 // div.wu
1987	case ADIVV:
1988		return 0x44 << 15 // div.d
1989	case ADIVVU:
1990		return 0x46 << 15 // div.du
1991	case AREM:
1992		return 0x41 << 15 // mod.w
1993	case AREMU:
1994		return 0x43 << 15 // mod.wu
1995	case AREMV:
1996		return 0x45 << 15 // mod.d
1997	case AREMVU:
1998		return 0x47 << 15 // mod.du
1999
2000	case AJMP:
2001		return 0x13 << 26 // jirl r0, rj, 0
2002	case AJAL:
2003		return (0x13 << 26) | 1 // jirl r1, rj, 0
2004
2005	case ADIVF:
2006		return 0x20d << 15
2007	case ADIVD:
2008		return 0x20e << 15
2009	case AMULF:
2010		return 0x209 << 15
2011	case AMULD:
2012		return 0x20a << 15
2013	case ASUBF:
2014		return 0x205 << 15
2015	case ASUBD:
2016		return 0x206 << 15
2017	case AADDF:
2018		return 0x201 << 15
2019	case AADDD:
2020		return 0x202 << 15
2021	case ATRUNCFV:
2022		return 0x46a9 << 10
2023	case ATRUNCDV:
2024		return 0x46aa << 10
2025	case ATRUNCFW:
2026		return 0x46a1 << 10
2027	case ATRUNCDW:
2028		return 0x46a2 << 10
2029	case AMOVFV:
2030		return 0x46c9 << 10
2031	case AMOVDV:
2032		return 0x46ca << 10
2033	case AMOVVF:
2034		return 0x4746 << 10
2035	case AMOVVD:
2036		return 0x474a << 10
2037	case AMOVFW:
2038		return 0x46c1 << 10
2039	case AMOVDW:
2040		return 0x46c2 << 10
2041	case AMOVWF:
2042		return 0x4744 << 10
2043	case AMOVDF:
2044		return 0x4646 << 10
2045	case AMOVWD:
2046		return 0x4748 << 10
2047	case AMOVFD:
2048		return 0x4649 << 10
2049	case AABSF:
2050		return 0x4501 << 10
2051	case AABSD:
2052		return 0x4502 << 10
2053	case AMOVF:
2054		return 0x4525 << 10
2055	case AMOVD:
2056		return 0x4526 << 10
2057	case ANEGF:
2058		return 0x4505 << 10
2059	case ANEGD:
2060		return 0x4506 << 10
2061	case ACMPEQF:
2062		return 0x0c1<<20 | 0x4<<15 // FCMP.CEQ.S
2063	case ACMPEQD:
2064		return 0x0c2<<20 | 0x4<<15 // FCMP.CEQ.D
2065	case ACMPGED:
2066		return 0x0c2<<20 | 0x7<<15 // FCMP.SLE.D
2067	case ACMPGEF:
2068		return 0x0c1<<20 | 0x7<<15 // FCMP.SLE.S
2069	case ACMPGTD:
2070		return 0x0c2<<20 | 0x3<<15 // FCMP.SLT.D
2071	case ACMPGTF:
2072		return 0x0c1<<20 | 0x3<<15 // FCMP.SLT.S
2073
2074	case ASQRTF:
2075		return 0x4511 << 10
2076	case ASQRTD:
2077		return 0x4512 << 10
2078	}
2079
2080	if a < 0 {
2081		c.ctxt.Diag("bad rrr opcode -%v", -a)
2082	} else {
2083		c.ctxt.Diag("bad rrr opcode %v", a)
2084	}
2085	return 0
2086}
2087
2088func (c *ctxt0) oprr(a obj.As) uint32 {
2089	switch a {
2090	case ACLO:
2091		return 0x4 << 10
2092	case ACLZ:
2093		return 0x5 << 10
2094	case ARDTIMELW:
2095		return 0x18 << 10
2096	case ARDTIMEHW:
2097		return 0x19 << 10
2098	case ARDTIMED:
2099		return 0x1a << 10
2100	}
2101
2102	c.ctxt.Diag("bad rr opcode %v", a)
2103	return 0
2104}
2105
2106func (c *ctxt0) opi(a obj.As) uint32 {
2107	switch a {
2108	case ASYSCALL:
2109		return 0x56 << 15
2110	case ABREAK:
2111		return 0x54 << 15
2112	case ADBAR:
2113		return 0x70e4 << 15
2114	}
2115
2116	c.ctxt.Diag("bad ic opcode %v", a)
2117
2118	return 0
2119}
2120
2121func (c *ctxt0) opir(a obj.As) uint32 {
2122	switch a {
2123	case ALU12IW:
2124		return 0x0a << 25
2125	case ALU32ID:
2126		return 0x0b << 25
2127	case APCALAU12I:
2128		return 0x0d << 25
2129	case APCADDU12I:
2130		return 0x0e << 25
2131	}
2132	return 0
2133}
2134
2135func (c *ctxt0) opirr(a obj.As) uint32 {
2136	switch a {
2137	case AADD, AADDU:
2138		return 0x00a << 22
2139	case ASGT:
2140		return 0x008 << 22
2141	case ASGTU:
2142		return 0x009 << 22
2143	case AAND:
2144		return 0x00d << 22
2145	case AOR:
2146		return 0x00e << 22
2147	case ALU52ID:
2148		return 0x00c << 22
2149	case AXOR:
2150		return 0x00f << 22
2151	case ASLL:
2152		return 0x00081 << 15
2153	case ASRL:
2154		return 0x00089 << 15
2155	case ASRA:
2156		return 0x00091 << 15
2157	case AROTR:
2158		return 0x00099 << 15
2159	case AADDV:
2160		return 0x00b << 22
2161	case AADDVU:
2162		return 0x00b << 22
2163
2164	case AJMP:
2165		return 0x14 << 26
2166	case AJAL,
2167		obj.ADUFFZERO,
2168		obj.ADUFFCOPY:
2169		return 0x15 << 26
2170
2171	case AJIRL:
2172		return 0x13 << 26
2173	case ABLTU:
2174		return 0x1a << 26
2175	case ABLT, ABLTZ, ABGTZ:
2176		return 0x18 << 26
2177	case ABGEU:
2178		return 0x1b << 26
2179	case ABGE, ABGEZ, ABLEZ:
2180		return 0x19 << 26
2181	case -ABEQ: // beqz
2182		return 0x10 << 26
2183	case -ABNE: // bnez
2184		return 0x11 << 26
2185	case ABEQ:
2186		return 0x16 << 26
2187	case ABNE:
2188		return 0x17 << 26
2189	case ABFPT:
2190		return 0x12<<26 | 0x1<<8
2191	case ABFPF:
2192		return 0x12<<26 | 0x0<<8
2193
2194	case AMOVB,
2195		AMOVBU:
2196		return 0x0a4 << 22
2197	case AMOVH,
2198		AMOVHU:
2199		return 0x0a5 << 22
2200	case AMOVW,
2201		AMOVWU:
2202		return 0x0a6 << 22
2203	case AMOVV:
2204		return 0x0a7 << 22
2205	case AMOVF:
2206		return 0x0ad << 22
2207	case AMOVD:
2208		return 0x0af << 22
2209	case AMOVWL:
2210		return 0x0bc << 22
2211	case AMOVWR:
2212		return 0x0bd << 22
2213	case AMOVVL:
2214		return 0x0be << 22
2215	case AMOVVR:
2216		return 0x0bf << 22
2217	case -AMOVWL:
2218		return 0x0b8 << 22
2219	case -AMOVWR:
2220		return 0x0b9 << 22
2221	case -AMOVVL:
2222		return 0x0ba << 22
2223	case -AMOVVR:
2224		return 0x0bb << 22
2225	case -AMOVB:
2226		return 0x0a0 << 22
2227	case -AMOVBU:
2228		return 0x0a8 << 22
2229	case -AMOVH:
2230		return 0x0a1 << 22
2231	case -AMOVHU:
2232		return 0x0a9 << 22
2233	case -AMOVW:
2234		return 0x0a2 << 22
2235	case -AMOVWU:
2236		return 0x0aa << 22
2237	case -AMOVV:
2238		return 0x0a3 << 22
2239	case -AMOVF:
2240		return 0x0ac << 22
2241	case -AMOVD:
2242		return 0x0ae << 22
2243
2244	case ASLLV,
2245		-ASLLV:
2246		return 0x0041 << 16
2247	case ASRLV,
2248		-ASRLV:
2249		return 0x0045 << 16
2250	case ASRAV,
2251		-ASRAV:
2252		return 0x0049 << 16
2253	case AROTRV,
2254		-AROTRV:
2255		return 0x004d << 16
2256	case -ALL:
2257		return 0x020 << 24
2258	case -ALLV:
2259		return 0x022 << 24
2260	case ASC:
2261		return 0x021 << 24
2262	case ASCV:
2263		return 0x023 << 24
2264	}
2265
2266	if a < 0 {
2267		c.ctxt.Diag("bad irr opcode -%v", -a)
2268	} else {
2269		c.ctxt.Diag("bad irr opcode %v", a)
2270	}
2271	return 0
2272}
2273
2274func vshift(a obj.As) bool {
2275	switch a {
2276	case ASLLV,
2277		ASRLV,
2278		ASRAV,
2279		AROTRV:
2280		return true
2281	}
2282	return false
2283}
2284