1// Inferno utils/5l/span.c
2// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/span.c
3//
4//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
5//	Portions Copyright © 1995-1997 C H Forsyth ([email protected])
6//	Portions Copyright © 1997-1999 Vita Nuova Limited
7//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8//	Portions Copyright © 2004,2006 Bruce Ellis
9//	Portions Copyright © 2005-2007 C H Forsyth ([email protected])
10//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11//	Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
31package arm
32
33import (
34	"cmd/internal/obj"
35	"cmd/internal/objabi"
36	"fmt"
37	"internal/buildcfg"
38	"log"
39	"math"
40	"sort"
41)
42
43// ctxt5 holds state while assembling a single function.
44// Each function gets a fresh ctxt5.
45// This allows for multiple functions to be safely concurrently assembled.
46type ctxt5 struct {
47	ctxt       *obj.Link
48	newprog    obj.ProgAlloc
49	cursym     *obj.LSym
50	printp     *obj.Prog
51	blitrl     *obj.Prog
52	elitrl     *obj.Prog
53	autosize   int64
54	instoffset int64
55	pc         int64
56	pool       struct {
57		start uint32
58		size  uint32
59		extra uint32
60	}
61}
62
63type Optab struct {
64	as       obj.As
65	a1       uint8
66	a2       int8
67	a3       uint8
68	type_    uint8
69	size     int8
70	param    int16
71	flag     int8
72	pcrelsiz uint8
73	scond    uint8 // optional flags accepted by the instruction
74}
75
76type Opcross [32][2][32]uint8
77
78const (
79	LFROM  = 1 << 0
80	LTO    = 1 << 1
81	LPOOL  = 1 << 2
82	LPCREL = 1 << 3
83)
84
85var optab = []Optab{
86	/* struct Optab:
87	OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */
88	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0},
89	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
90	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
91	{AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
92	{AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
93	{AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
94	{AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
95	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
96	{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
97	{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0},
98	{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
99	{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
100	{AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
101	{AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
102	{AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
103	{AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
104	{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
105	{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
106	{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0},
107	{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
108	{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
109	{AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
110	{AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
111	{AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
112	{AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
113	{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
114	{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0},
115	{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT},
116	{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0},
117	{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
118	{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0},
119	{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
120	{ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored
121	{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0},
122	{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
123	{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
124	{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0},
125	{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0},
126	{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT},
127	{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT},
128	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT},
129	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT},
130	{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0},
131	{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0},
132	{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0},
133	{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0},
134	{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0},
135	{AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0},
136	{AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0},
137	{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
138	{AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
139	{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0},
140	{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0},
141	{AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
142	{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
143	{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
144	{AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
145	{AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
146	{AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
147	{AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
148	{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
149	{AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
150	{AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
151	{AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
152	{AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
153	{AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
154	{AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
155	{AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0},
156	{ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
157	{AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
158	{AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
159	{AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
160	{AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
161	{AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0},
162	{AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0},
163	{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
164	{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
165	{AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
166	{AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
167	{AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
168	{AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
169	{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0},
170	{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0},
171	{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
172	{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
173	{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0},
174	{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
175	{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
176	{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
177	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT},
178	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT},
179	{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0},
180	{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0},
181	{ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0},
182	{ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0},
183	{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT},
184	{ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0},  // width in From, LSB in From3
185	{ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3
186	{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
187	{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
188	{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
189	{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
190	{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
191	{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
192	{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
193	{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
194	{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
195	{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
196	{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
197	{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
198	{AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0},
199	{AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0},
200	{AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT},
201	{AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
202	{AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
203	{AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
204	{AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
205	{AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
206	{AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
207	{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
208	{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
209	{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
210	{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
211	{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
212	{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
213	{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
214	{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
215	{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
216	{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
217	{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
218	{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
219	{AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0},
220	{AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0},
221	{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
222	{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
223	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
224	{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
225	{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
226	{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
227	{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT},
228	{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0},
229	{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0},
230	{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0},
231	{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
232	{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
233	{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0},
234	{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0},
235	{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
236	{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
237	{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
238	{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
239	{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
240	{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
241	{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
242	{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
243	{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
244	{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
245	{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0},
246	{AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0},
247	{AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
248	{ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
249	{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0},
250	{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0},
251	{AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
252	{AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
253	{AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
254	{AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
255	{AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
256	{AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
257	{AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
258	{AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
259	{AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
260	{AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
261	{AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
262	{AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
263	{AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
264	{AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
265	{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
266	{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
267	{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
268	{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
269	{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
270	{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
271	{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
272	{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
273	{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
274	{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
275	{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
276	{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
277	{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
278	{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
279	{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
280	{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
281	{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
282	{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
283	{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
284	{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
285	{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
286	{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
287	{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
288	{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
289	{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
290	{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
291	{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
292	{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
293	{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
294	{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
295	{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
296	{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
297	{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
298	{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
299	{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
300	{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
301	{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
302	{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
303	{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
304	{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
305	{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0},
306	{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0},
307	{ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
308	{ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
309	{ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
310	{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0},
311	{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0},
312	{ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0},
313	{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0},
314	{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT},
315	{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT},
316	{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT},
317	{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT},
318	{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
319	{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
320	{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
321	{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
322	{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
323	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
324	{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
325	{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0},
326	{AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT},
327	{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0},
328	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0},
329	{obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0},
330	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
331	{obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, // nop variants, see #40689
332	{obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
333	{obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
334	{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
335	{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
336	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0},
337}
338
339var mbOp = []struct {
340	reg int16
341	enc uint32
342}{
343	{REG_MB_SY, 15},
344	{REG_MB_ST, 14},
345	{REG_MB_ISH, 11},
346	{REG_MB_ISHST, 10},
347	{REG_MB_NSH, 7},
348	{REG_MB_NSHST, 6},
349	{REG_MB_OSH, 3},
350	{REG_MB_OSHST, 2},
351}
352
353var oprange [ALAST & obj.AMask][]Optab
354
355var xcmp [C_GOK + 1][C_GOK + 1]bool
356
357var (
358	symdiv  *obj.LSym
359	symdivu *obj.LSym
360	symmod  *obj.LSym
361	symmodu *obj.LSym
362)
363
364// Note about encoding: Prog.scond holds the condition encoding,
365// but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
366// The code that shifts the value << 28 has the responsibility
367// for XORing with C_SCOND_XOR too.
368
369func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) {
370	if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 {
371		c.ctxt.Diag("invalid .S suffix: %v", p)
372	}
373	if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 {
374		c.ctxt.Diag("invalid .P suffix: %v", p)
375	}
376	if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 {
377		c.ctxt.Diag("invalid .W suffix: %v", p)
378	}
379	if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 {
380		c.ctxt.Diag("invalid .U suffix: %v", p)
381	}
382}
383
384func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
385	if ctxt.Retpoline {
386		ctxt.Diag("-spectre=ret not supported on arm")
387		ctxt.Retpoline = false // don't keep printing
388	}
389
390	var p *obj.Prog
391	var op *obj.Prog
392
393	p = cursym.Func().Text
394	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
395		return
396	}
397
398	if oprange[AAND&obj.AMask] == nil {
399		ctxt.Diag("arm ops not initialized, call arm.buildop first")
400	}
401
402	c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4}
403	pc := int32(0)
404
405	op = p
406	p = p.Link
407	var m int
408	var o *Optab
409	for ; p != nil || c.blitrl != nil; op, p = p, p.Link {
410		if p == nil {
411			if c.checkpool(op, pc) {
412				p = op
413				continue
414			}
415
416			// can't happen: blitrl is not nil, but checkpool didn't flushpool
417			ctxt.Diag("internal inconsistency")
418
419			break
420		}
421
422		p.Pc = int64(pc)
423		o = c.oplook(p)
424		m = int(o.size)
425
426		if m%4 != 0 || p.Pc%4 != 0 {
427			ctxt.Diag("!pc invalid: %v size=%d", p, m)
428		}
429
430		// must check literal pool here in case p generates many instructions
431		if c.blitrl != nil {
432			// Emit the constant pool just before p if p
433			// would push us over the immediate size limit.
434			if c.checkpool(op, pc+int32(m)) {
435				// Back up to the instruction just
436				// before the pool and continue with
437				// the first instruction of the pool.
438				p = op
439				continue
440			}
441		}
442
443		if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
444			ctxt.Diag("zero-width instruction\n%v", p)
445			continue
446		}
447
448		switch o.flag & (LFROM | LTO | LPOOL) {
449		case LFROM:
450			c.addpool(p, &p.From)
451
452		case LTO:
453			c.addpool(p, &p.To)
454
455		case LPOOL:
456			if p.Scond&C_SCOND == C_SCOND_NONE {
457				c.flushpool(p, 0, 0)
458			}
459		}
460
461		if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
462			c.flushpool(p, 0, 0)
463		}
464
465		pc += int32(m)
466	}
467
468	c.cursym.Size = int64(pc)
469
470	/*
471	 * if any procedure is large enough to
472	 * generate a large SBRA branch, then
473	 * generate extra passes putting branches
474	 * around jmps to fix. this is rare.
475	 */
476	times := 0
477
478	var bflag int
479	var opc int32
480	var out [6 + 3]uint32
481	for {
482		bflag = 0
483		pc = 0
484		times++
485		c.cursym.Func().Text.Pc = 0 // force re-layout the code.
486		for p = c.cursym.Func().Text; p != nil; p = p.Link {
487			o = c.oplook(p)
488			if int64(pc) > p.Pc {
489				p.Pc = int64(pc)
490			}
491
492			/* very large branches
493			if(o->type == 6 && p->pcond) {
494				otxt = p->pcond->pc - c;
495				if(otxt < 0)
496					otxt = -otxt;
497				if(otxt >= (1L<<17) - 10) {
498					q = emallocz(sizeof(Prog));
499					q->link = p->link;
500					p->link = q;
501					q->as = AB;
502					q->to.type = TYPE_BRANCH;
503					q->pcond = p->pcond;
504					p->pcond = q;
505					q = emallocz(sizeof(Prog));
506					q->link = p->link;
507					p->link = q;
508					q->as = AB;
509					q->to.type = TYPE_BRANCH;
510					q->pcond = q->link->link;
511					bflag = 1;
512				}
513			}
514			*/
515			opc = int32(p.Pc)
516			m = int(o.size)
517			if p.Pc != int64(opc) {
518				bflag = 1
519			}
520
521			//print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
522			pc = int32(p.Pc + int64(m))
523
524			if m%4 != 0 || p.Pc%4 != 0 {
525				ctxt.Diag("pc invalid: %v size=%d", p, m)
526			}
527
528			if m/4 > len(out) {
529				ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
530			}
531			if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
532				if p.As == obj.ATEXT {
533					c.autosize = p.To.Offset + 4
534					continue
535				}
536
537				ctxt.Diag("zero-width instruction\n%v", p)
538				continue
539			}
540		}
541
542		c.cursym.Size = int64(pc)
543		if bflag == 0 {
544			break
545		}
546	}
547
548	if pc%4 != 0 {
549		ctxt.Diag("sym->size=%d, invalid", pc)
550	}
551
552	/*
553	 * lay out the code.  all the pc-relative code references,
554	 * even cross-function, are resolved now;
555	 * only data references need to be relocated.
556	 * with more work we could leave cross-function
557	 * code references to be relocated too, and then
558	 * perhaps we'd be able to parallelize the span loop above.
559	 */
560
561	p = c.cursym.Func().Text
562	c.autosize = p.To.Offset + 4
563	c.cursym.Grow(c.cursym.Size)
564
565	bp := c.cursym.P
566	pc = int32(p.Pc) // even p->link might need extra padding
567	var v int
568	for p = p.Link; p != nil; p = p.Link {
569		c.pc = p.Pc
570		o = c.oplook(p)
571		opc = int32(p.Pc)
572		c.asmout(p, o, out[:])
573		m = int(o.size)
574
575		if m%4 != 0 || p.Pc%4 != 0 {
576			ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
577		}
578
579		if int64(pc) > p.Pc {
580			ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p)
581		}
582		for int64(pc) != p.Pc {
583			// emit 0xe1a00000 (MOVW R0, R0)
584			bp[0] = 0x00
585			bp = bp[1:]
586
587			bp[0] = 0x00
588			bp = bp[1:]
589			bp[0] = 0xa0
590			bp = bp[1:]
591			bp[0] = 0xe1
592			bp = bp[1:]
593			pc += 4
594		}
595
596		for i := 0; i < m/4; i++ {
597			v = int(out[i])
598			bp[0] = byte(v)
599			bp = bp[1:]
600			bp[0] = byte(v >> 8)
601			bp = bp[1:]
602			bp[0] = byte(v >> 16)
603			bp = bp[1:]
604			bp[0] = byte(v >> 24)
605			bp = bp[1:]
606		}
607
608		pc += int32(m)
609	}
610}
611
612// checkpool flushes the literal pool when the first reference to
613// it threatens to go out of range of a 12-bit PC-relative offset.
614//
615// nextpc is the tentative next PC at which the pool could be emitted.
616// checkpool should be called *before* emitting the instruction that
617// would cause the PC to reach nextpc.
618// If nextpc is too far from the first pool reference, checkpool will
619// flush the pool immediately after p.
620// The caller should resume processing a p.Link.
621func (c *ctxt5) checkpool(p *obj.Prog, nextpc int32) bool {
622	poolLast := nextpc
623	poolLast += 4                      // the AB instruction to jump around the pool
624	poolLast += int32(c.pool.size) - 4 // the offset of the last pool entry
625
626	refPC := int32(c.pool.start) // PC of the first pool reference
627
628	v := poolLast - refPC - 8 // 12-bit PC-relative offset (see omvl)
629
630	if c.pool.size >= 0xff0 || immaddr(v) == 0 {
631		return c.flushpool(p, 1, 0)
632	} else if p.Link == nil {
633		return c.flushpool(p, 2, 0)
634	}
635	return false
636}
637
638func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool {
639	if c.blitrl != nil {
640		if skip != 0 {
641			if false && skip == 1 {
642				fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
643			}
644			q := c.newprog()
645			q.As = AB
646			q.To.Type = obj.TYPE_BRANCH
647			q.To.SetTarget(p.Link)
648			q.Link = c.blitrl
649			q.Pos = p.Pos
650			c.blitrl = q
651		} else if force == 0 && (p.Pc+int64(c.pool.size)-int64(c.pool.start) < 2048) {
652			return false
653		}
654
655		// The line number for constant pool entries doesn't really matter.
656		// We set it to the line number of the preceding instruction so that
657		// there are no deltas to encode in the pc-line tables.
658		for q := c.blitrl; q != nil; q = q.Link {
659			q.Pos = p.Pos
660		}
661
662		c.elitrl.Link = p.Link
663		p.Link = c.blitrl
664
665		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
666		c.elitrl = nil
667		c.pool.size = 0
668		c.pool.start = 0
669		c.pool.extra = 0
670		return true
671	}
672
673	return false
674}
675
676func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) {
677	t := c.newprog()
678	t.As = AWORD
679
680	switch c.aclass(a) {
681	default:
682		t.To.Offset = a.Offset
683		t.To.Sym = a.Sym
684		t.To.Type = a.Type
685		t.To.Name = a.Name
686
687		if c.ctxt.Flag_shared && t.To.Sym != nil {
688			t.Rel = p
689		}
690
691	case C_HOREG,
692		C_FOREG,
693		C_HFOREG,
694		C_SOREG,
695		C_ROREG,
696		C_SROREG,
697		C_LOREG,
698		C_HAUTO,
699		C_FAUTO,
700		C_HFAUTO,
701		C_SAUTO,
702		C_LAUTO,
703		C_LACON:
704		t.To.Type = obj.TYPE_CONST
705		t.To.Offset = c.instoffset
706	}
707
708	if t.Rel == nil {
709		for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
710			if q.Rel == nil && q.To == t.To {
711				p.Pool = q
712				return
713			}
714		}
715	}
716
717	q := c.newprog()
718	*q = *t
719	q.Pc = int64(c.pool.size)
720
721	if c.blitrl == nil {
722		c.blitrl = q
723		c.pool.start = uint32(p.Pc)
724	} else {
725		c.elitrl.Link = q
726	}
727	c.elitrl = q
728	c.pool.size += 4
729
730	// Store the link to the pool entry in Pool.
731	p.Pool = q
732}
733
734func (c *ctxt5) regoff(a *obj.Addr) int32 {
735	c.instoffset = 0
736	c.aclass(a)
737	return int32(c.instoffset)
738}
739
740func immrot(v uint32) int32 {
741	for i := 0; i < 16; i++ {
742		if v&^0xff == 0 {
743			return int32(uint32(int32(i)<<8) | v | 1<<25)
744		}
745		v = v<<2 | v>>30
746	}
747
748	return 0
749}
750
751// immrot2a returns bits encoding the immediate constant fields of two instructions,
752// such that the encoded constants x, y satisfy x|y==v, x&y==0.
753// Returns 0,0 if no such decomposition of v exists.
754func immrot2a(v uint32) (uint32, uint32) {
755	for i := uint(1); i < 32; i++ {
756		m := uint32(1<<i - 1)
757		if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 {
758			return uint32(x), uint32(y)
759		}
760	}
761	// TODO: handle some more cases, like where
762	// the wraparound from the rotate could help.
763	return 0, 0
764}
765
766// immrot2s returns bits encoding the immediate constant fields of two instructions,
767// such that the encoded constants y, x satisfy y-x==v, y&x==0.
768// Returns 0,0 if no such decomposition of v exists.
769func immrot2s(v uint32) (uint32, uint32) {
770	if immrot(v) != 0 {
771		return v, 0
772	}
773	// suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
774	// omit trailing 00
775	var i uint32
776	for i = 2; i < 32; i += 2 {
777		if v&(1<<i-1) != 0 {
778			break
779		}
780	}
781	// i must be <= 24, then adjust i just above lower 8 effective bits of v
782	i += 6
783	// let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
784	x := 1<<i - v&(1<<i-1)
785	y := v + x
786	if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 {
787		return y, x
788	}
789	return 0, 0
790}
791
792func immaddr(v int32) int32 {
793	if v >= 0 && v <= 0xfff {
794		return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
795	}
796	if v >= -0xfff && v < 0 {
797		return -v&0xfff | 1<<24 /* pre indexing */
798	}
799	return 0
800}
801
802func immfloat(v int32) bool {
803	return v&0xC03 == 0 /* offset will fit in floating-point load/store */
804}
805
806func immhalf(v int32) bool {
807	if v >= 0 && v <= 0xff {
808		return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
809	}
810	if v >= -0xff && v < 0 {
811		return -v&0xff|1<<24 != 0 /* pre indexing */
812	}
813	return false
814}
815
816func (c *ctxt5) aclass(a *obj.Addr) int {
817	switch a.Type {
818	case obj.TYPE_NONE:
819		return C_NONE
820
821	case obj.TYPE_REG:
822		c.instoffset = 0
823		if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
824			return C_REG
825		}
826		if REG_F0 <= a.Reg && a.Reg <= REG_F15 {
827			return C_FREG
828		}
829		if a.Reg == REG_FPSR || a.Reg == REG_FPCR {
830			return C_FCR
831		}
832		if a.Reg == REG_CPSR || a.Reg == REG_SPSR {
833			return C_PSR
834		}
835		if a.Reg >= REG_SPECIAL {
836			return C_SPR
837		}
838		return C_GOK
839
840	case obj.TYPE_REGREG:
841		return C_REGREG
842
843	case obj.TYPE_REGREG2:
844		return C_REGREG2
845
846	case obj.TYPE_REGLIST:
847		return C_REGLIST
848
849	case obj.TYPE_SHIFT:
850		if a.Reg == 0 {
851			// register shift R>>i
852			return C_SHIFT
853		} else {
854			// memory address with shifted offset R>>i(R)
855			return C_SHIFTADDR
856		}
857
858	case obj.TYPE_MEM:
859		switch a.Name {
860		case obj.NAME_EXTERN,
861			obj.NAME_GOTREF,
862			obj.NAME_STATIC:
863			if a.Sym == nil || a.Sym.Name == "" {
864				fmt.Printf("null sym external\n")
865				return C_GOK
866			}
867
868			c.instoffset = 0 // s.b. unused but just in case
869			if a.Sym.Type == objabi.STLSBSS {
870				if c.ctxt.Flag_shared {
871					return C_TLS_IE
872				} else {
873					return C_TLS_LE
874				}
875			}
876
877			return C_ADDR
878
879		case obj.NAME_AUTO:
880			if a.Reg == REGSP {
881				// unset base register for better printing, since
882				// a.Offset is still relative to pseudo-SP.
883				a.Reg = obj.REG_NONE
884			}
885			c.instoffset = c.autosize + a.Offset
886			if t := immaddr(int32(c.instoffset)); t != 0 {
887				if immhalf(int32(c.instoffset)) {
888					if immfloat(t) {
889						return C_HFAUTO
890					}
891					return C_HAUTO
892				}
893
894				if immfloat(t) {
895					return C_FAUTO
896				}
897				return C_SAUTO
898			}
899
900			return C_LAUTO
901
902		case obj.NAME_PARAM:
903			if a.Reg == REGSP {
904				// unset base register for better printing, since
905				// a.Offset is still relative to pseudo-FP.
906				a.Reg = obj.REG_NONE
907			}
908			c.instoffset = c.autosize + a.Offset + 4
909			if t := immaddr(int32(c.instoffset)); t != 0 {
910				if immhalf(int32(c.instoffset)) {
911					if immfloat(t) {
912						return C_HFAUTO
913					}
914					return C_HAUTO
915				}
916
917				if immfloat(t) {
918					return C_FAUTO
919				}
920				return C_SAUTO
921			}
922
923			return C_LAUTO
924
925		case obj.NAME_NONE:
926			c.instoffset = a.Offset
927			if t := immaddr(int32(c.instoffset)); t != 0 {
928				if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
929					if immfloat(t) {
930						return C_HFOREG
931					}
932					return C_HOREG
933				}
934
935				if immfloat(t) {
936					return C_FOREG /* n.b. that it will also satisfy immrot */
937				}
938				if immrot(uint32(c.instoffset)) != 0 {
939					return C_SROREG
940				}
941				if immhalf(int32(c.instoffset)) {
942					return C_HOREG
943				}
944				return C_SOREG
945			}
946
947			if immrot(uint32(c.instoffset)) != 0 {
948				return C_ROREG
949			}
950			return C_LOREG
951		}
952
953		return C_GOK
954
955	case obj.TYPE_FCONST:
956		if c.chipzero5(a.Val.(float64)) >= 0 {
957			return C_ZFCON
958		}
959		if c.chipfloat5(a.Val.(float64)) >= 0 {
960			return C_SFCON
961		}
962		return C_LFCON
963
964	case obj.TYPE_TEXTSIZE:
965		return C_TEXTSIZE
966
967	case obj.TYPE_CONST,
968		obj.TYPE_ADDR:
969		switch a.Name {
970		case obj.NAME_NONE:
971			c.instoffset = a.Offset
972			if a.Reg != 0 {
973				return c.aconsize()
974			}
975
976			if immrot(uint32(c.instoffset)) != 0 {
977				return C_RCON
978			}
979			if immrot(^uint32(c.instoffset)) != 0 {
980				return C_NCON
981			}
982			if uint32(c.instoffset) <= 0xffff && buildcfg.GOARM.Version == 7 {
983				return C_SCON
984			}
985			if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
986				return C_RCON2A
987			}
988			if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
989				return C_RCON2S
990			}
991			return C_LCON
992
993		case obj.NAME_EXTERN,
994			obj.NAME_GOTREF,
995			obj.NAME_STATIC:
996			s := a.Sym
997			if s == nil {
998				break
999			}
1000			c.instoffset = 0 // s.b. unused but just in case
1001			return C_LCONADDR
1002
1003		case obj.NAME_AUTO:
1004			if a.Reg == REGSP {
1005				// unset base register for better printing, since
1006				// a.Offset is still relative to pseudo-SP.
1007				a.Reg = obj.REG_NONE
1008			}
1009			c.instoffset = c.autosize + a.Offset
1010			return c.aconsize()
1011
1012		case obj.NAME_PARAM:
1013			if a.Reg == REGSP {
1014				// unset base register for better printing, since
1015				// a.Offset is still relative to pseudo-FP.
1016				a.Reg = obj.REG_NONE
1017			}
1018			c.instoffset = c.autosize + a.Offset + 4
1019			return c.aconsize()
1020		}
1021
1022		return C_GOK
1023
1024	case obj.TYPE_BRANCH:
1025		return C_SBRA
1026	}
1027
1028	return C_GOK
1029}
1030
1031func (c *ctxt5) aconsize() int {
1032	if immrot(uint32(c.instoffset)) != 0 {
1033		return C_RACON
1034	}
1035	if immrot(uint32(-c.instoffset)) != 0 {
1036		return C_RACON
1037	}
1038	return C_LACON
1039}
1040
1041func (c *ctxt5) oplook(p *obj.Prog) *Optab {
1042	a1 := int(p.Optab)
1043	if a1 != 0 {
1044		return &optab[a1-1]
1045	}
1046	a1 = int(p.From.Class)
1047	if a1 == 0 {
1048		a1 = c.aclass(&p.From) + 1
1049		p.From.Class = int8(a1)
1050	}
1051
1052	a1--
1053	a3 := int(p.To.Class)
1054	if a3 == 0 {
1055		a3 = c.aclass(&p.To) + 1
1056		p.To.Class = int8(a3)
1057	}
1058
1059	a3--
1060	a2 := C_NONE
1061	if p.Reg != 0 {
1062		switch {
1063		case REG_F0 <= p.Reg && p.Reg <= REG_F15:
1064			a2 = C_FREG
1065		case REG_R0 <= p.Reg && p.Reg <= REG_R15:
1066			a2 = C_REG
1067		default:
1068			c.ctxt.Diag("invalid register in %v", p)
1069		}
1070	}
1071
1072	// check illegal base register
1073	switch a1 {
1074	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
1075		if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
1076			c.ctxt.Diag("illegal base register: %v", p)
1077		}
1078	default:
1079	}
1080	switch a3 {
1081	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
1082		if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
1083			c.ctxt.Diag("illegal base register: %v", p)
1084		}
1085	default:
1086	}
1087
1088	// If current instruction has a .S suffix (flags update),
1089	// we must use the constant pool instead of splitting it.
1090	if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
1091		a1 = C_LCON
1092	}
1093	if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
1094		a3 = C_LCON
1095	}
1096
1097	if false { /*debug['O']*/
1098		fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
1099		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
1100	}
1101
1102	if (p.As == ASRL || p.As == ASRA) && p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 {
1103		// Right shifts are weird - a shift that looks like "shift by constant 0" actually
1104		// means "shift by constant 32". Use left shift in this situation instead.
1105		// See issue 64715.
1106		// TODO: rotate by 0? Not currently supported, but if we ever do then include it here.
1107		p.As = ASLL
1108	}
1109	if p.As != AMOVB && p.As != AMOVBS && p.As != AMOVBU && p.As != AMOVH && p.As != AMOVHS && p.As != AMOVHU && p.As != AXTAB && p.As != AXTABU && p.As != AXTAH && p.As != AXTAHU {
1110		// Same here, but for shifts encoded in Addrs.
1111		// Don't do it for the extension ops, which
1112		// need to keep their RR shifts.
1113		fixShift := func(a *obj.Addr) {
1114			if a.Type == obj.TYPE_SHIFT {
1115				typ := a.Offset & SHIFT_RR
1116				isConst := a.Offset&(1<<4) == 0
1117				amount := a.Offset >> 7 & 0x1f
1118				if isConst && amount == 0 && (typ == SHIFT_LR || typ == SHIFT_AR || typ == SHIFT_RR) {
1119					a.Offset -= typ
1120					a.Offset += SHIFT_LL
1121				}
1122			}
1123		}
1124		fixShift(&p.From)
1125		fixShift(&p.To)
1126	}
1127
1128	ops := oprange[p.As&obj.AMask]
1129	c1 := &xcmp[a1]
1130	c3 := &xcmp[a3]
1131	for i := range ops {
1132		op := &ops[i]
1133		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
1134			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
1135			checkSuffix(c, p, op)
1136			return op
1137		}
1138	}
1139
1140	c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name)
1141	if ops == nil {
1142		ops = optab
1143	}
1144	return &ops[0]
1145}
1146
1147func cmp(a int, b int) bool {
1148	if a == b {
1149		return true
1150	}
1151	switch a {
1152	case C_LCON:
1153		if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
1154			return true
1155		}
1156
1157	case C_LACON:
1158		if b == C_RACON {
1159			return true
1160		}
1161
1162	case C_LFCON:
1163		if b == C_ZFCON || b == C_SFCON {
1164			return true
1165		}
1166
1167	case C_HFAUTO:
1168		return b == C_HAUTO || b == C_FAUTO
1169
1170	case C_FAUTO, C_HAUTO:
1171		return b == C_HFAUTO
1172
1173	case C_SAUTO:
1174		return cmp(C_HFAUTO, b)
1175
1176	case C_LAUTO:
1177		return cmp(C_SAUTO, b)
1178
1179	case C_HFOREG:
1180		return b == C_HOREG || b == C_FOREG
1181
1182	case C_FOREG, C_HOREG:
1183		return b == C_HFOREG
1184
1185	case C_SROREG:
1186		return cmp(C_SOREG, b) || cmp(C_ROREG, b)
1187
1188	case C_SOREG, C_ROREG:
1189		return b == C_SROREG || cmp(C_HFOREG, b)
1190
1191	case C_LOREG:
1192		return cmp(C_SROREG, b)
1193
1194	case C_LBRA:
1195		if b == C_SBRA {
1196			return true
1197		}
1198
1199	case C_HREG:
1200		return cmp(C_SP, b) || cmp(C_PC, b)
1201	}
1202
1203	return false
1204}
1205
1206type ocmp []Optab
1207
1208func (x ocmp) Len() int {
1209	return len(x)
1210}
1211
1212func (x ocmp) Swap(i, j int) {
1213	x[i], x[j] = x[j], x[i]
1214}
1215
1216func (x ocmp) Less(i, j int) bool {
1217	p1 := &x[i]
1218	p2 := &x[j]
1219	n := int(p1.as) - int(p2.as)
1220	if n != 0 {
1221		return n < 0
1222	}
1223	n = int(p1.a1) - int(p2.a1)
1224	if n != 0 {
1225		return n < 0
1226	}
1227	n = int(p1.a2) - int(p2.a2)
1228	if n != 0 {
1229		return n < 0
1230	}
1231	n = int(p1.a3) - int(p2.a3)
1232	if n != 0 {
1233		return n < 0
1234	}
1235	return false
1236}
1237
1238func opset(a, b0 obj.As) {
1239	oprange[a&obj.AMask] = oprange[b0]
1240}
1241
1242func buildop(ctxt *obj.Link) {
1243	if oprange[AAND&obj.AMask] != nil {
1244		// Already initialized; stop now.
1245		// This happens in the cmd/asm tests,
1246		// each of which re-initializes the arch.
1247		return
1248	}
1249
1250	symdiv = ctxt.Lookup("runtime._div")
1251	symdivu = ctxt.Lookup("runtime._divu")
1252	symmod = ctxt.Lookup("runtime._mod")
1253	symmodu = ctxt.Lookup("runtime._modu")
1254
1255	var n int
1256
1257	for i := 0; i < C_GOK; i++ {
1258		for n = 0; n < C_GOK; n++ {
1259			if cmp(n, i) {
1260				xcmp[i][n] = true
1261			}
1262		}
1263	}
1264	for n = 0; optab[n].as != obj.AXXX; n++ {
1265		if optab[n].flag&LPCREL != 0 {
1266			if ctxt.Flag_shared {
1267				optab[n].size += int8(optab[n].pcrelsiz)
1268			} else {
1269				optab[n].flag &^= LPCREL
1270			}
1271		}
1272	}
1273
1274	sort.Sort(ocmp(optab[:n]))
1275	for i := 0; i < n; i++ {
1276		r := optab[i].as
1277		r0 := r & obj.AMask
1278		start := i
1279		for optab[i].as == r {
1280			i++
1281		}
1282		oprange[r0] = optab[start:i]
1283		i--
1284
1285		switch r {
1286		default:
1287			ctxt.Diag("unknown op in build: %v", r)
1288			ctxt.DiagFlush()
1289			log.Fatalf("bad code")
1290
1291		case AADD:
1292			opset(ASUB, r0)
1293			opset(ARSB, r0)
1294			opset(AADC, r0)
1295			opset(ASBC, r0)
1296			opset(ARSC, r0)
1297
1298		case AORR:
1299			opset(AEOR, r0)
1300			opset(ABIC, r0)
1301
1302		case ACMP:
1303			opset(ATEQ, r0)
1304			opset(ACMN, r0)
1305			opset(ATST, r0)
1306
1307		case AMVN:
1308			break
1309
1310		case ABEQ:
1311			opset(ABNE, r0)
1312			opset(ABCS, r0)
1313			opset(ABHS, r0)
1314			opset(ABCC, r0)
1315			opset(ABLO, r0)
1316			opset(ABMI, r0)
1317			opset(ABPL, r0)
1318			opset(ABVS, r0)
1319			opset(ABVC, r0)
1320			opset(ABHI, r0)
1321			opset(ABLS, r0)
1322			opset(ABGE, r0)
1323			opset(ABLT, r0)
1324			opset(ABGT, r0)
1325			opset(ABLE, r0)
1326
1327		case ASLL:
1328			opset(ASRL, r0)
1329			opset(ASRA, r0)
1330
1331		case AMUL:
1332			opset(AMULU, r0)
1333
1334		case ADIV:
1335			opset(AMOD, r0)
1336			opset(AMODU, r0)
1337			opset(ADIVU, r0)
1338
1339		case ADIVHW:
1340			opset(ADIVUHW, r0)
1341
1342		case AMOVW,
1343			AMOVB,
1344			AMOVBS,
1345			AMOVBU,
1346			AMOVH,
1347			AMOVHS,
1348			AMOVHU:
1349			break
1350
1351		case ASWPW:
1352			opset(ASWPBU, r0)
1353
1354		case AB,
1355			ABL,
1356			ABX,
1357			ABXRET,
1358			obj.ADUFFZERO,
1359			obj.ADUFFCOPY,
1360			ASWI,
1361			AWORD,
1362			AMOVM,
1363			ARFE,
1364			obj.ATEXT:
1365			break
1366
1367		case AADDF:
1368			opset(AADDD, r0)
1369			opset(ASUBF, r0)
1370			opset(ASUBD, r0)
1371			opset(AMULF, r0)
1372			opset(AMULD, r0)
1373			opset(ANMULF, r0)
1374			opset(ANMULD, r0)
1375			opset(AMULAF, r0)
1376			opset(AMULAD, r0)
1377			opset(AMULSF, r0)
1378			opset(AMULSD, r0)
1379			opset(ANMULAF, r0)
1380			opset(ANMULAD, r0)
1381			opset(ANMULSF, r0)
1382			opset(ANMULSD, r0)
1383			opset(AFMULAF, r0)
1384			opset(AFMULAD, r0)
1385			opset(AFMULSF, r0)
1386			opset(AFMULSD, r0)
1387			opset(AFNMULAF, r0)
1388			opset(AFNMULAD, r0)
1389			opset(AFNMULSF, r0)
1390			opset(AFNMULSD, r0)
1391			opset(ADIVF, r0)
1392			opset(ADIVD, r0)
1393
1394		case ANEGF:
1395			opset(ANEGD, r0)
1396			opset(ASQRTF, r0)
1397			opset(ASQRTD, r0)
1398			opset(AMOVFD, r0)
1399			opset(AMOVDF, r0)
1400			opset(AABSF, r0)
1401			opset(AABSD, r0)
1402
1403		case ACMPF:
1404			opset(ACMPD, r0)
1405
1406		case AMOVF:
1407			opset(AMOVD, r0)
1408
1409		case AMOVFW:
1410			opset(AMOVDW, r0)
1411
1412		case AMOVWF:
1413			opset(AMOVWD, r0)
1414
1415		case AMULL:
1416			opset(AMULAL, r0)
1417			opset(AMULLU, r0)
1418			opset(AMULALU, r0)
1419
1420		case AMULWT:
1421			opset(AMULWB, r0)
1422			opset(AMULBB, r0)
1423			opset(AMMUL, r0)
1424
1425		case AMULAWT:
1426			opset(AMULAWB, r0)
1427			opset(AMULABB, r0)
1428			opset(AMULS, r0)
1429			opset(AMMULA, r0)
1430			opset(AMMULS, r0)
1431
1432		case ABFX:
1433			opset(ABFXU, r0)
1434			opset(ABFC, r0)
1435			opset(ABFI, r0)
1436
1437		case ACLZ:
1438			opset(AREV, r0)
1439			opset(AREV16, r0)
1440			opset(AREVSH, r0)
1441			opset(ARBIT, r0)
1442
1443		case AXTAB:
1444			opset(AXTAH, r0)
1445			opset(AXTABU, r0)
1446			opset(AXTAHU, r0)
1447
1448		case ALDREX,
1449			ASTREX,
1450			ALDREXD,
1451			ASTREXD,
1452			ADMB,
1453			APLD,
1454			AAND,
1455			AMULA,
1456			obj.AUNDEF,
1457			obj.AFUNCDATA,
1458			obj.APCDATA,
1459			obj.ANOP:
1460			break
1461		}
1462	}
1463}
1464
1465func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
1466	c.printp = p
1467	o1 := uint32(0)
1468	o2 := uint32(0)
1469	o3 := uint32(0)
1470	o4 := uint32(0)
1471	o5 := uint32(0)
1472	o6 := uint32(0)
1473	if false { /*debug['P']*/
1474		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
1475	}
1476	switch o.type_ {
1477	default:
1478		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
1479
1480	case 0: /* pseudo ops */
1481		if false { /*debug['G']*/
1482			fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
1483		}
1484
1485	case 1: /* op R,[R],R */
1486		o1 = c.oprrr(p, p.As, int(p.Scond))
1487
1488		rf := int(p.From.Reg)
1489		rt := int(p.To.Reg)
1490		r := int(p.Reg)
1491		if p.To.Type == obj.TYPE_NONE {
1492			rt = 0
1493		}
1494		if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
1495			r = 0
1496		} else if r == 0 {
1497			r = rt
1498		}
1499		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1500
1501	case 2: /* movbu $I,[R],R */
1502		c.aclass(&p.From)
1503
1504		o1 = c.oprrr(p, p.As, int(p.Scond))
1505		o1 |= uint32(immrot(uint32(c.instoffset)))
1506		rt := int(p.To.Reg)
1507		r := int(p.Reg)
1508		if p.To.Type == obj.TYPE_NONE {
1509			rt = 0
1510		}
1511		if p.As == AMOVW || p.As == AMVN {
1512			r = 0
1513		} else if r == 0 {
1514			r = rt
1515		}
1516		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1517
1518	case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
1519		c.aclass(&p.From)
1520		r := int(p.Reg)
1521		rt := int(p.To.Reg)
1522		if r == 0 {
1523			r = rt
1524		}
1525		x, y := immrot2a(uint32(c.instoffset))
1526		var as2 obj.As
1527		switch p.As {
1528		case AADD, ASUB, AORR, AEOR, ABIC:
1529			as2 = p.As // ADD, SUB, ORR, EOR, BIC
1530		case ARSB:
1531			as2 = AADD // RSB -> RSB/ADD pair
1532		case AADC:
1533			as2 = AADD // ADC -> ADC/ADD pair
1534		case ASBC:
1535			as2 = ASUB // SBC -> SBC/SUB pair
1536		case ARSC:
1537			as2 = AADD // RSC -> RSC/ADD pair
1538		default:
1539			c.ctxt.Diag("unknown second op for %v", p)
1540		}
1541		o1 = c.oprrr(p, p.As, int(p.Scond))
1542		o2 = c.oprrr(p, as2, int(p.Scond))
1543		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1544		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1545		o1 |= x
1546		o2 |= y
1547
1548	case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
1549		c.aclass(&p.From)
1550		r := int(p.Reg)
1551		rt := int(p.To.Reg)
1552		if r == 0 {
1553			r = rt
1554		}
1555		y, x := immrot2s(uint32(c.instoffset))
1556		var as2 obj.As
1557		switch p.As {
1558		case AADD:
1559			as2 = ASUB // ADD -> ADD/SUB pair
1560		case ASUB:
1561			as2 = AADD // SUB -> SUB/ADD pair
1562		case ARSB:
1563			as2 = ASUB // RSB -> RSB/SUB pair
1564		case AADC:
1565			as2 = ASUB // ADC -> ADC/SUB pair
1566		case ASBC:
1567			as2 = AADD // SBC -> SBC/ADD pair
1568		case ARSC:
1569			as2 = ASUB // RSC -> RSC/SUB pair
1570		default:
1571			c.ctxt.Diag("unknown second op for %v", p)
1572		}
1573		o1 = c.oprrr(p, p.As, int(p.Scond))
1574		o2 = c.oprrr(p, as2, int(p.Scond))
1575		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1576		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1577		o1 |= y
1578		o2 |= x
1579
1580	case 3: /* add R<<[IR],[R],R */
1581		o1 = c.mov(p)
1582
1583	case 4: /* MOVW $off(R), R -> add $off,[R],R */
1584		c.aclass(&p.From)
1585		if c.instoffset < 0 {
1586			o1 = c.oprrr(p, ASUB, int(p.Scond))
1587			o1 |= uint32(immrot(uint32(-c.instoffset)))
1588		} else {
1589			o1 = c.oprrr(p, AADD, int(p.Scond))
1590			o1 |= uint32(immrot(uint32(c.instoffset)))
1591		}
1592		r := int(p.From.Reg)
1593		if r == 0 {
1594			r = int(o.param)
1595		}
1596		o1 |= (uint32(r) & 15) << 16
1597		o1 |= (uint32(p.To.Reg) & 15) << 12
1598
1599	case 5: /* bra s */
1600		o1 = c.opbra(p, p.As, int(p.Scond))
1601
1602		v := int32(-8)
1603		if p.To.Sym != nil {
1604			rel := obj.Addrel(c.cursym)
1605			rel.Off = int32(c.pc)
1606			rel.Siz = 4
1607			rel.Sym = p.To.Sym
1608			v += int32(p.To.Offset)
1609			rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
1610			rel.Type = objabi.R_CALLARM
1611			break
1612		}
1613
1614		if p.To.Target() != nil {
1615			v = int32((p.To.Target().Pc - c.pc) - 8)
1616		}
1617		o1 |= (uint32(v) >> 2) & 0xffffff
1618
1619	case 6: /* b ,O(R) -> add $O,R,PC */
1620		c.aclass(&p.To)
1621
1622		o1 = c.oprrr(p, AADD, int(p.Scond))
1623		o1 |= uint32(immrot(uint32(c.instoffset)))
1624		o1 |= (uint32(p.To.Reg) & 15) << 16
1625		o1 |= (REGPC & 15) << 12
1626
1627	case 7: /* bl (R) -> blx R */
1628		c.aclass(&p.To)
1629
1630		if c.instoffset != 0 {
1631			c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
1632		}
1633		o1 = c.oprrr(p, ABL, int(p.Scond))
1634		o1 |= (uint32(p.To.Reg) & 15) << 0
1635		rel := obj.Addrel(c.cursym)
1636		rel.Off = int32(c.pc)
1637		rel.Siz = 0
1638		rel.Type = objabi.R_CALLIND
1639
1640	case 8: /* sll $c,[R],R -> mov (R<<$c),R */
1641		c.aclass(&p.From)
1642
1643		o1 = c.oprrr(p, p.As, int(p.Scond))
1644		r := int(p.Reg)
1645		if r == 0 {
1646			r = int(p.To.Reg)
1647		}
1648		o1 |= (uint32(r) & 15) << 0
1649		o1 |= uint32((c.instoffset & 31) << 7)
1650		o1 |= (uint32(p.To.Reg) & 15) << 12
1651
1652	case 9: /* sll R,[R],R -> mov (R<<R),R */
1653		o1 = c.oprrr(p, p.As, int(p.Scond))
1654
1655		r := int(p.Reg)
1656		if r == 0 {
1657			r = int(p.To.Reg)
1658		}
1659		o1 |= (uint32(r) & 15) << 0
1660		o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
1661		o1 |= (uint32(p.To.Reg) & 15) << 12
1662
1663	case 10: /* swi [$con] */
1664		o1 = c.oprrr(p, p.As, int(p.Scond))
1665
1666		if p.To.Type != obj.TYPE_NONE {
1667			c.aclass(&p.To)
1668			o1 |= uint32(c.instoffset & 0xffffff)
1669		}
1670
1671	case 11: /* word */
1672		c.aclass(&p.To)
1673
1674		o1 = uint32(c.instoffset)
1675		if p.To.Sym != nil {
1676			// This case happens with words generated
1677			// in the PC stream as part of the literal pool (c.pool).
1678			rel := obj.Addrel(c.cursym)
1679
1680			rel.Off = int32(c.pc)
1681			rel.Siz = 4
1682			rel.Sym = p.To.Sym
1683			rel.Add = p.To.Offset
1684
1685			if c.ctxt.Flag_shared {
1686				if p.To.Name == obj.NAME_GOTREF {
1687					rel.Type = objabi.R_GOTPCREL
1688				} else {
1689					rel.Type = objabi.R_PCREL
1690				}
1691				rel.Add += c.pc - p.Rel.Pc - 8
1692			} else {
1693				rel.Type = objabi.R_ADDR
1694			}
1695			o1 = 0
1696		}
1697
1698	case 12: /* movw $lcon, reg */
1699		if o.a1 == C_SCON {
1700			o1 = c.omvs(p, &p.From, int(p.To.Reg))
1701		} else if p.As == AMVN {
1702			o1 = c.omvr(p, &p.From, int(p.To.Reg))
1703		} else {
1704			o1 = c.omvl(p, &p.From, int(p.To.Reg))
1705		}
1706
1707		if o.flag&LPCREL != 0 {
1708			o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
1709		}
1710
1711	case 13: /* op $lcon, [R], R */
1712		if o.a1 == C_SCON {
1713			o1 = c.omvs(p, &p.From, REGTMP)
1714		} else {
1715			o1 = c.omvl(p, &p.From, REGTMP)
1716		}
1717
1718		if o1 == 0 {
1719			break
1720		}
1721		o2 = c.oprrr(p, p.As, int(p.Scond))
1722		o2 |= REGTMP & 15
1723		r := int(p.Reg)
1724		if p.As == AMVN {
1725			r = 0
1726		} else if r == 0 {
1727			r = int(p.To.Reg)
1728		}
1729		o2 |= (uint32(r) & 15) << 16
1730		if p.To.Type != obj.TYPE_NONE {
1731			o2 |= (uint32(p.To.Reg) & 15) << 12
1732		}
1733
1734	case 14: /* movb/movbu/movh/movhu R,R */
1735		o1 = c.oprrr(p, ASLL, int(p.Scond))
1736
1737		if p.As == AMOVBU || p.As == AMOVHU {
1738			o2 = c.oprrr(p, ASRL, int(p.Scond))
1739		} else {
1740			o2 = c.oprrr(p, ASRA, int(p.Scond))
1741		}
1742
1743		r := int(p.To.Reg)
1744		o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
1745		o2 |= uint32(r)&15 | (uint32(r)&15)<<12
1746		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
1747			o1 |= 24 << 7
1748			o2 |= 24 << 7
1749		} else {
1750			o1 |= 16 << 7
1751			o2 |= 16 << 7
1752		}
1753
1754	case 15: /* mul r,[r,]r */
1755		o1 = c.oprrr(p, p.As, int(p.Scond))
1756
1757		rf := int(p.From.Reg)
1758		rt := int(p.To.Reg)
1759		r := int(p.Reg)
1760		if r == 0 {
1761			r = rt
1762		}
1763
1764		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
1765
1766	case 16: /* div r,[r,]r */
1767		o1 = 0xf << 28
1768
1769		o2 = 0
1770
1771	case 17:
1772		o1 = c.oprrr(p, p.As, int(p.Scond))
1773		rf := int(p.From.Reg)
1774		rt := int(p.To.Reg)
1775		rt2 := int(p.To.Offset)
1776		r := int(p.Reg)
1777		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
1778
1779	case 18: /* BFX/BFXU/BFC/BFI */
1780		o1 = c.oprrr(p, p.As, int(p.Scond))
1781		rt := int(p.To.Reg)
1782		r := int(p.Reg)
1783		if r == 0 {
1784			r = rt
1785		} else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0
1786			c.ctxt.Diag("illegal combination: %v", p)
1787		}
1788		if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
1789			c.ctxt.Diag("%v: missing or wrong LSB", p)
1790			break
1791		}
1792		lsb := p.GetFrom3().Offset
1793		width := p.From.Offset
1794		if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
1795			c.ctxt.Diag("%v: wrong width or LSB", p)
1796		}
1797		switch p.As {
1798		case ABFX, ABFXU: // (width-1) is encoded
1799			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
1800		case ABFC, ABFI: // MSB is encoded
1801			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
1802		default:
1803			c.ctxt.Diag("illegal combination: %v", p)
1804		}
1805
1806	case 20: /* mov/movb/movbu R,O(R) */
1807		c.aclass(&p.To)
1808
1809		r := int(p.To.Reg)
1810		if r == 0 {
1811			r = int(o.param)
1812		}
1813		o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
1814
1815	case 21: /* mov/movbu O(R),R -> lr */
1816		c.aclass(&p.From)
1817
1818		r := int(p.From.Reg)
1819		if r == 0 {
1820			r = int(o.param)
1821		}
1822		o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
1823		if p.As != AMOVW {
1824			o1 |= 1 << 22
1825		}
1826
1827	case 22: /* XTAB R@>i, [R], R */
1828		o1 = c.oprrr(p, p.As, int(p.Scond))
1829		switch p.From.Offset &^ 0xf {
1830		// only 0/8/16/24 bits rotation is accepted
1831		case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
1832			o1 |= uint32(p.From.Offset) & 0xc0f
1833		default:
1834			c.ctxt.Diag("illegal shift: %v", p)
1835		}
1836		rt := p.To.Reg
1837		r := p.Reg
1838		if r == 0 {
1839			r = rt
1840		}
1841		o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
1842
1843	case 23: /* MOVW/MOVB/MOVH R@>i, R */
1844		switch p.As {
1845		case AMOVW:
1846			o1 = c.mov(p)
1847		case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
1848			o1 = c.movxt(p)
1849		default:
1850			c.ctxt.Diag("illegal combination: %v", p)
1851		}
1852
1853	case 30: /* mov/movb/movbu R,L(R) */
1854		o1 = c.omvl(p, &p.To, REGTMP)
1855
1856		if o1 == 0 {
1857			break
1858		}
1859		r := int(p.To.Reg)
1860		if r == 0 {
1861			r = int(o.param)
1862		}
1863		o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
1864		if p.As != AMOVW {
1865			o2 |= 1 << 22
1866		}
1867
1868	case 31: /* mov/movbu L(R),R -> lr[b] */
1869		o1 = c.omvl(p, &p.From, REGTMP)
1870
1871		if o1 == 0 {
1872			break
1873		}
1874		r := int(p.From.Reg)
1875		if r == 0 {
1876			r = int(o.param)
1877		}
1878		o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
1879		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
1880			o2 |= 1 << 22
1881		}
1882
1883	case 34: /* mov $lacon,R */
1884		o1 = c.omvl(p, &p.From, REGTMP)
1885
1886		if o1 == 0 {
1887			break
1888		}
1889
1890		o2 = c.oprrr(p, AADD, int(p.Scond))
1891		o2 |= REGTMP & 15
1892		r := int(p.From.Reg)
1893		if r == 0 {
1894			r = int(o.param)
1895		}
1896		o2 |= (uint32(r) & 15) << 16
1897		if p.To.Type != obj.TYPE_NONE {
1898			o2 |= (uint32(p.To.Reg) & 15) << 12
1899		}
1900
1901	case 35: /* mov PSR,R */
1902		o1 = 2<<23 | 0xf<<16 | 0<<0
1903
1904		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1905		o1 |= (uint32(p.From.Reg) & 1) << 22
1906		o1 |= (uint32(p.To.Reg) & 15) << 12
1907
1908	case 36: /* mov R,PSR */
1909		o1 = 2<<23 | 0x2cf<<12 | 0<<4
1910
1911		if p.Scond&C_FBIT != 0 {
1912			o1 ^= 0x010 << 12
1913		}
1914		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1915		o1 |= (uint32(p.To.Reg) & 1) << 22
1916		o1 |= (uint32(p.From.Reg) & 15) << 0
1917
1918	case 37: /* mov $con,PSR */
1919		c.aclass(&p.From)
1920
1921		o1 = 2<<23 | 0x2cf<<12 | 0<<4
1922		if p.Scond&C_FBIT != 0 {
1923			o1 ^= 0x010 << 12
1924		}
1925		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1926		o1 |= uint32(immrot(uint32(c.instoffset)))
1927		o1 |= (uint32(p.To.Reg) & 1) << 22
1928		o1 |= (uint32(p.From.Reg) & 15) << 0
1929
1930	case 38, 39:
1931		switch o.type_ {
1932		case 38: /* movm $con,oreg -> stm */
1933			o1 = 0x4 << 25
1934
1935			o1 |= uint32(p.From.Offset & 0xffff)
1936			o1 |= (uint32(p.To.Reg) & 15) << 16
1937			c.aclass(&p.To)
1938
1939		case 39: /* movm oreg,$con -> ldm */
1940			o1 = 0x4<<25 | 1<<20
1941
1942			o1 |= uint32(p.To.Offset & 0xffff)
1943			o1 |= (uint32(p.From.Reg) & 15) << 16
1944			c.aclass(&p.From)
1945		}
1946
1947		if c.instoffset != 0 {
1948			c.ctxt.Diag("offset must be zero in MOVM; %v", p)
1949		}
1950		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1951		if p.Scond&C_PBIT != 0 {
1952			o1 |= 1 << 24
1953		}
1954		if p.Scond&C_UBIT != 0 {
1955			o1 |= 1 << 23
1956		}
1957		if p.Scond&C_WBIT != 0 {
1958			o1 |= 1 << 21
1959		}
1960
1961	case 40: /* swp oreg,reg,reg */
1962		c.aclass(&p.From)
1963
1964		if c.instoffset != 0 {
1965			c.ctxt.Diag("offset must be zero in SWP")
1966		}
1967		o1 = 0x2<<23 | 0x9<<4
1968		if p.As != ASWPW {
1969			o1 |= 1 << 22
1970		}
1971		o1 |= (uint32(p.From.Reg) & 15) << 16
1972		o1 |= (uint32(p.Reg) & 15) << 0
1973		o1 |= (uint32(p.To.Reg) & 15) << 12
1974		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1975
1976	case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
1977		o1 = 0xe8fd8000
1978
1979	case 50: /* floating point store */
1980		v := c.regoff(&p.To)
1981
1982		r := int(p.To.Reg)
1983		if r == 0 {
1984			r = int(o.param)
1985		}
1986		o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
1987
1988	case 51: /* floating point load */
1989		v := c.regoff(&p.From)
1990
1991		r := int(p.From.Reg)
1992		if r == 0 {
1993			r = int(o.param)
1994		}
1995		o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
1996
1997	case 52: /* floating point store, int32 offset UGLY */
1998		o1 = c.omvl(p, &p.To, REGTMP)
1999
2000		if o1 == 0 {
2001			break
2002		}
2003		r := int(p.To.Reg)
2004		if r == 0 {
2005			r = int(o.param)
2006		}
2007		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
2008		o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
2009
2010	case 53: /* floating point load, int32 offset UGLY */
2011		o1 = c.omvl(p, &p.From, REGTMP)
2012
2013		if o1 == 0 {
2014			break
2015		}
2016		r := int(p.From.Reg)
2017		if r == 0 {
2018			r = int(o.param)
2019		}
2020		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
2021		o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
2022
2023	case 54: /* floating point arith */
2024		o1 = c.oprrr(p, p.As, int(p.Scond))
2025
2026		rf := int(p.From.Reg)
2027		rt := int(p.To.Reg)
2028		r := int(p.Reg)
2029		if r == 0 {
2030			switch p.As {
2031			case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
2032				AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
2033				c.ctxt.Diag("illegal combination: %v", p)
2034			default:
2035				r = rt
2036			}
2037		}
2038
2039		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2040
2041	case 55: /* negf freg, freg */
2042		o1 = c.oprrr(p, p.As, int(p.Scond))
2043
2044		rf := int(p.From.Reg)
2045		rt := int(p.To.Reg)
2046
2047		o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
2048
2049	case 56: /* move to FP[CS]R */
2050		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
2051
2052		o1 |= (uint32(p.From.Reg) & 15) << 12
2053
2054	case 57: /* move from FP[CS]R */
2055		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
2056
2057		o1 |= (uint32(p.To.Reg) & 15) << 12
2058
2059	case 58: /* movbu R,R */
2060		o1 = c.oprrr(p, AAND, int(p.Scond))
2061
2062		o1 |= uint32(immrot(0xff))
2063		rt := int(p.To.Reg)
2064		r := int(p.From.Reg)
2065		if p.To.Type == obj.TYPE_NONE {
2066			rt = 0
2067		}
2068		if r == 0 {
2069			r = rt
2070		}
2071		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2072
2073	case 59: /* movw/bu R<<I(R),R -> ldr indexed */
2074		if p.From.Reg == 0 {
2075			c.ctxt.Diag("source operand is not a memory address: %v", p)
2076			break
2077		}
2078		if p.From.Offset&(1<<4) != 0 {
2079			c.ctxt.Diag("bad shift in LDR")
2080			break
2081		}
2082		o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2083		if p.As == AMOVBU {
2084			o1 |= 1 << 22
2085		}
2086
2087	case 60: /* movb R(R),R -> ldrsb indexed */
2088		if p.From.Reg == 0 {
2089			c.ctxt.Diag("source operand is not a memory address: %v", p)
2090			break
2091		}
2092		if p.From.Offset&(^0xf) != 0 {
2093			c.ctxt.Diag("bad shift: %v", p)
2094			break
2095		}
2096		o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2097		switch p.As {
2098		case AMOVB, AMOVBS:
2099			o1 ^= 1<<5 | 1<<6
2100		case AMOVH, AMOVHS:
2101			o1 ^= 1 << 6
2102		default:
2103		}
2104		if p.Scond&C_UBIT != 0 {
2105			o1 &^= 1 << 23
2106		}
2107
2108	case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
2109		if p.To.Reg == 0 {
2110			c.ctxt.Diag("MOV to shifter operand")
2111		}
2112		o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
2113		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
2114			o1 |= 1 << 22
2115		}
2116
2117	case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */
2118		if p.To.Reg == 0 {
2119			c.ctxt.Diag("MOV to shifter operand")
2120		}
2121		if p.To.Offset&(^0xf) != 0 {
2122			c.ctxt.Diag("bad shift: %v", p)
2123		}
2124		o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
2125		o1 ^= 1 << 20
2126		if p.Scond&C_UBIT != 0 {
2127			o1 &^= 1 << 23
2128		}
2129
2130		/* reloc ops */
2131	case 64: /* mov/movb/movbu R,addr */
2132		o1 = c.omvl(p, &p.To, REGTMP)
2133
2134		if o1 == 0 {
2135			break
2136		}
2137		o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
2138		if o.flag&LPCREL != 0 {
2139			o3 = o2
2140			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2141		}
2142
2143	case 65: /* mov/movbu addr,R */
2144		o1 = c.omvl(p, &p.From, REGTMP)
2145
2146		if o1 == 0 {
2147			break
2148		}
2149		o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2150		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
2151			o2 |= 1 << 22
2152		}
2153		if o.flag&LPCREL != 0 {
2154			o3 = o2
2155			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2156		}
2157
2158	case 101: /* movw tlsvar,R, local exec*/
2159		o1 = c.omvl(p, &p.From, int(p.To.Reg))
2160
2161	case 102: /* movw tlsvar,R, initial exec*/
2162		o1 = c.omvl(p, &p.From, int(p.To.Reg))
2163		o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
2164
2165	case 103: /* word tlsvar, local exec */
2166		if p.To.Sym == nil {
2167			c.ctxt.Diag("nil sym in tls %v", p)
2168		}
2169		if p.To.Offset != 0 {
2170			c.ctxt.Diag("offset against tls var in %v", p)
2171		}
2172		// This case happens with words generated in the PC stream as part of
2173		// the literal c.pool.
2174		rel := obj.Addrel(c.cursym)
2175
2176		rel.Off = int32(c.pc)
2177		rel.Siz = 4
2178		rel.Sym = p.To.Sym
2179		rel.Type = objabi.R_TLS_LE
2180		o1 = 0
2181
2182	case 104: /* word tlsvar, initial exec */
2183		if p.To.Sym == nil {
2184			c.ctxt.Diag("nil sym in tls %v", p)
2185		}
2186		if p.To.Offset != 0 {
2187			c.ctxt.Diag("offset against tls var in %v", p)
2188		}
2189		rel := obj.Addrel(c.cursym)
2190		rel.Off = int32(c.pc)
2191		rel.Siz = 4
2192		rel.Sym = p.To.Sym
2193		rel.Type = objabi.R_TLS_IE
2194		rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
2195
2196	case 68: /* floating point store -> ADDR */
2197		o1 = c.omvl(p, &p.To, REGTMP)
2198
2199		if o1 == 0 {
2200			break
2201		}
2202		o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
2203		if o.flag&LPCREL != 0 {
2204			o3 = o2
2205			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2206		}
2207
2208	case 69: /* floating point load <- ADDR */
2209		o1 = c.omvl(p, &p.From, REGTMP)
2210
2211		if o1 == 0 {
2212			break
2213		}
2214		o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
2215		if o.flag&LPCREL != 0 {
2216			o3 = o2
2217			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2218		}
2219
2220		/* ArmV4 ops: */
2221	case 70: /* movh/movhu R,O(R) -> strh */
2222		c.aclass(&p.To)
2223
2224		r := int(p.To.Reg)
2225		if r == 0 {
2226			r = int(o.param)
2227		}
2228		o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
2229
2230	case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
2231		c.aclass(&p.From)
2232
2233		r := int(p.From.Reg)
2234		if r == 0 {
2235			r = int(o.param)
2236		}
2237		o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
2238		if p.As == AMOVB || p.As == AMOVBS {
2239			o1 ^= 1<<5 | 1<<6
2240		} else if p.As == AMOVH || p.As == AMOVHS {
2241			o1 ^= (1 << 6)
2242		}
2243
2244	case 72: /* movh/movhu R,L(R) -> strh */
2245		o1 = c.omvl(p, &p.To, REGTMP)
2246
2247		if o1 == 0 {
2248			break
2249		}
2250		r := int(p.To.Reg)
2251		if r == 0 {
2252			r = int(o.param)
2253		}
2254		o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
2255
2256	case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
2257		o1 = c.omvl(p, &p.From, REGTMP)
2258
2259		if o1 == 0 {
2260			break
2261		}
2262		r := int(p.From.Reg)
2263		if r == 0 {
2264			r = int(o.param)
2265		}
2266		o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
2267		if p.As == AMOVB || p.As == AMOVBS {
2268			o2 ^= 1<<5 | 1<<6
2269		} else if p.As == AMOVH || p.As == AMOVHS {
2270			o2 ^= (1 << 6)
2271		}
2272
2273	case 74: /* bx $I */
2274		c.ctxt.Diag("ABX $I")
2275
2276	case 75: /* bx O(R) */
2277		c.aclass(&p.To)
2278
2279		if c.instoffset != 0 {
2280			c.ctxt.Diag("non-zero offset in ABX")
2281		}
2282
2283		/*
2284			o1 = 	c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12);	// mov PC, LR
2285			o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0);		// BX R
2286		*/
2287		// p->to.reg may be REGLINK
2288		o1 = c.oprrr(p, AADD, int(p.Scond))
2289
2290		o1 |= uint32(immrot(uint32(c.instoffset)))
2291		o1 |= (uint32(p.To.Reg) & 15) << 16
2292		o1 |= (REGTMP & 15) << 12
2293		o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
2294		o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15            // BX Rtmp
2295
2296	case 76: /* bx O(R) when returning from fn*/
2297		c.ctxt.Diag("ABXRET")
2298
2299	case 77: /* ldrex oreg,reg */
2300		c.aclass(&p.From)
2301
2302		if c.instoffset != 0 {
2303			c.ctxt.Diag("offset must be zero in LDREX")
2304		}
2305		o1 = 0x19<<20 | 0xf9f
2306		o1 |= (uint32(p.From.Reg) & 15) << 16
2307		o1 |= (uint32(p.To.Reg) & 15) << 12
2308		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2309
2310	case 78: /* strex reg,oreg,reg */
2311		c.aclass(&p.From)
2312
2313		if c.instoffset != 0 {
2314			c.ctxt.Diag("offset must be zero in STREX")
2315		}
2316		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
2317			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2318		}
2319		o1 = 0x18<<20 | 0xf90
2320		o1 |= (uint32(p.From.Reg) & 15) << 16
2321		o1 |= (uint32(p.Reg) & 15) << 0
2322		o1 |= (uint32(p.To.Reg) & 15) << 12
2323		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2324
2325	case 80: /* fmov zfcon,freg */
2326		if p.As == AMOVD {
2327			o1 = 0xeeb00b00 // VMOV imm 64
2328			o2 = c.oprrr(p, ASUBD, int(p.Scond))
2329		} else {
2330			o1 = 0x0eb00a00 // VMOV imm 32
2331			o2 = c.oprrr(p, ASUBF, int(p.Scond))
2332		}
2333
2334		v := int32(0x70) // 1.0
2335		r := (int(p.To.Reg) & 15) << 0
2336
2337		// movf $1.0, r
2338		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2339
2340		o1 |= (uint32(r) & 15) << 12
2341		o1 |= (uint32(v) & 0xf) << 0
2342		o1 |= (uint32(v) & 0xf0) << 12
2343
2344		// subf r,r,r
2345		o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
2346
2347	case 81: /* fmov sfcon,freg */
2348		o1 = 0x0eb00a00 // VMOV imm 32
2349		if p.As == AMOVD {
2350			o1 = 0xeeb00b00 // VMOV imm 64
2351		}
2352		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2353		o1 |= (uint32(p.To.Reg) & 15) << 12
2354		v := int32(c.chipfloat5(p.From.Val.(float64)))
2355		o1 |= (uint32(v) & 0xf) << 0
2356		o1 |= (uint32(v) & 0xf0) << 12
2357
2358	case 82: /* fcmp freg,freg, */
2359		o1 = c.oprrr(p, p.As, int(p.Scond))
2360
2361		o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
2362		o2 = 0x0ef1fa10 // VMRS R15
2363		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2364
2365	case 83: /* fcmp freg,, */
2366		o1 = c.oprrr(p, p.As, int(p.Scond))
2367
2368		o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
2369		o2 = 0x0ef1fa10 // VMRS R15
2370		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2371
2372	case 84: /* movfw freg,freg - truncate float-to-fix */
2373		o1 = c.oprrr(p, p.As, int(p.Scond))
2374
2375		o1 |= (uint32(p.From.Reg) & 15) << 0
2376		o1 |= (uint32(p.To.Reg) & 15) << 12
2377
2378	case 85: /* movwf freg,freg - fix-to-float */
2379		o1 = c.oprrr(p, p.As, int(p.Scond))
2380
2381		o1 |= (uint32(p.From.Reg) & 15) << 0
2382		o1 |= (uint32(p.To.Reg) & 15) << 12
2383
2384		// macro for movfw freg,FTMP; movw FTMP,reg
2385	case 86: /* movfw freg,reg - truncate float-to-fix */
2386		o1 = c.oprrr(p, p.As, int(p.Scond))
2387
2388		o1 |= (uint32(p.From.Reg) & 15) << 0
2389		o1 |= (FREGTMP & 15) << 12
2390		o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
2391		o2 |= (FREGTMP & 15) << 16
2392		o2 |= (uint32(p.To.Reg) & 15) << 12
2393
2394		// macro for movw reg,FTMP; movwf FTMP,freg
2395	case 87: /* movwf reg,freg - fix-to-float */
2396		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2397
2398		o1 |= (uint32(p.From.Reg) & 15) << 12
2399		o1 |= (FREGTMP & 15) << 16
2400		o2 = c.oprrr(p, p.As, int(p.Scond))
2401		o2 |= (FREGTMP & 15) << 0
2402		o2 |= (uint32(p.To.Reg) & 15) << 12
2403
2404	case 88: /* movw reg,freg  */
2405		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2406
2407		o1 |= (uint32(p.From.Reg) & 15) << 12
2408		o1 |= (uint32(p.To.Reg) & 15) << 16
2409
2410	case 89: /* movw freg,reg  */
2411		o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
2412
2413		o1 |= (uint32(p.From.Reg) & 15) << 16
2414		o1 |= (uint32(p.To.Reg) & 15) << 12
2415
2416	case 91: /* ldrexd oreg,reg */
2417		c.aclass(&p.From)
2418
2419		if c.instoffset != 0 {
2420			c.ctxt.Diag("offset must be zero in LDREX")
2421		}
2422		o1 = 0x1b<<20 | 0xf9f
2423		o1 |= (uint32(p.From.Reg) & 15) << 16
2424		o1 |= (uint32(p.To.Reg) & 15) << 12
2425		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2426
2427	case 92: /* strexd reg,oreg,reg */
2428		c.aclass(&p.From)
2429
2430		if c.instoffset != 0 {
2431			c.ctxt.Diag("offset must be zero in STREX")
2432		}
2433		if p.Reg&1 != 0 {
2434			c.ctxt.Diag("source register must be even in STREXD: %v", p)
2435		}
2436		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
2437			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2438		}
2439		o1 = 0x1a<<20 | 0xf90
2440		o1 |= (uint32(p.From.Reg) & 15) << 16
2441		o1 |= (uint32(p.Reg) & 15) << 0
2442		o1 |= (uint32(p.To.Reg) & 15) << 12
2443		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2444
2445	case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
2446		o1 = c.omvl(p, &p.From, REGTMP)
2447
2448		if o1 == 0 {
2449			break
2450		}
2451		o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2452		if p.As == AMOVB || p.As == AMOVBS {
2453			o2 ^= 1<<5 | 1<<6
2454		} else if p.As == AMOVH || p.As == AMOVHS {
2455			o2 ^= (1 << 6)
2456		}
2457		if o.flag&LPCREL != 0 {
2458			o3 = o2
2459			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2460		}
2461
2462	case 94: /* movh/movhu R,addr -> strh */
2463		o1 = c.omvl(p, &p.To, REGTMP)
2464
2465		if o1 == 0 {
2466			break
2467		}
2468		o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
2469		if o.flag&LPCREL != 0 {
2470			o3 = o2
2471			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2472		}
2473
2474	case 95: /* PLD off(reg) */
2475		o1 = 0xf5d0f000
2476
2477		o1 |= (uint32(p.From.Reg) & 15) << 16
2478		if p.From.Offset < 0 {
2479			o1 &^= (1 << 23)
2480			o1 |= uint32((-p.From.Offset) & 0xfff)
2481		} else {
2482			o1 |= uint32(p.From.Offset & 0xfff)
2483		}
2484
2485	// This is supposed to be something that stops execution.
2486	// It's not supposed to be reached, ever, but if it is, we'd
2487	// like to be able to tell how we got there. Assemble as
2488	// 0xf7fabcfd which is guaranteed to raise undefined instruction
2489	// exception.
2490	case 96: /* UNDEF */
2491		o1 = 0xf7fabcfd
2492
2493	case 97: /* CLZ Rm, Rd */
2494		o1 = c.oprrr(p, p.As, int(p.Scond))
2495
2496		o1 |= (uint32(p.To.Reg) & 15) << 12
2497		o1 |= (uint32(p.From.Reg) & 15) << 0
2498
2499	case 98: /* MULW{T,B} Rs, Rm, Rd */
2500		o1 = c.oprrr(p, p.As, int(p.Scond))
2501
2502		o1 |= (uint32(p.To.Reg) & 15) << 16
2503		o1 |= (uint32(p.From.Reg) & 15) << 8
2504		o1 |= (uint32(p.Reg) & 15) << 0
2505
2506	case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
2507		o1 = c.oprrr(p, p.As, int(p.Scond))
2508
2509		o1 |= (uint32(p.To.Reg) & 15) << 16
2510		o1 |= (uint32(p.From.Reg) & 15) << 8
2511		o1 |= (uint32(p.Reg) & 15) << 0
2512		o1 |= uint32((p.To.Offset & 15) << 12)
2513
2514	case 105: /* divhw r,[r,]r */
2515		o1 = c.oprrr(p, p.As, int(p.Scond))
2516		rf := int(p.From.Reg)
2517		rt := int(p.To.Reg)
2518		r := int(p.Reg)
2519		if r == 0 {
2520			r = rt
2521		}
2522		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
2523
2524	case 110: /* dmb [mbop | $con] */
2525		o1 = 0xf57ff050
2526		mbop := uint32(0)
2527
2528		switch c.aclass(&p.From) {
2529		case C_SPR:
2530			for _, f := range mbOp {
2531				if f.reg == p.From.Reg {
2532					mbop = f.enc
2533					break
2534				}
2535			}
2536		case C_RCON:
2537			for _, f := range mbOp {
2538				enc := uint32(c.instoffset)
2539				if f.enc == enc {
2540					mbop = enc
2541					break
2542				}
2543			}
2544		case C_NONE:
2545			mbop = 0xf
2546		}
2547
2548		if mbop == 0 {
2549			c.ctxt.Diag("illegal mb option:\n%v", p)
2550		}
2551		o1 |= mbop
2552	}
2553
2554	out[0] = o1
2555	out[1] = o2
2556	out[2] = o3
2557	out[3] = o4
2558	out[4] = o5
2559	out[5] = o6
2560}
2561
2562func (c *ctxt5) movxt(p *obj.Prog) uint32 {
2563	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2564	switch p.As {
2565	case AMOVB, AMOVBS:
2566		o1 |= 0x6af<<16 | 0x7<<4
2567	case AMOVH, AMOVHS:
2568		o1 |= 0x6bf<<16 | 0x7<<4
2569	case AMOVBU:
2570		o1 |= 0x6ef<<16 | 0x7<<4
2571	case AMOVHU:
2572		o1 |= 0x6ff<<16 | 0x7<<4
2573	default:
2574		c.ctxt.Diag("illegal combination: %v", p)
2575	}
2576	switch p.From.Offset &^ 0xf {
2577	// only 0/8/16/24 bits rotation is accepted
2578	case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
2579		o1 |= uint32(p.From.Offset) & 0xc0f
2580	default:
2581		c.ctxt.Diag("illegal shift: %v", p)
2582	}
2583	o1 |= (uint32(p.To.Reg) & 15) << 12
2584	return o1
2585}
2586
2587func (c *ctxt5) mov(p *obj.Prog) uint32 {
2588	c.aclass(&p.From)
2589	o1 := c.oprrr(p, p.As, int(p.Scond))
2590	o1 |= uint32(p.From.Offset)
2591	rt := int(p.To.Reg)
2592	if p.To.Type == obj.TYPE_NONE {
2593		rt = 0
2594	}
2595	r := int(p.Reg)
2596	if p.As == AMOVW || p.As == AMVN {
2597		r = 0
2598	} else if r == 0 {
2599		r = rt
2600	}
2601	o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2602	return o1
2603}
2604
2605func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
2606	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2607	if sc&C_SBIT != 0 {
2608		o |= 1 << 20
2609	}
2610	switch a {
2611	case ADIVHW:
2612		return o | 0x71<<20 | 0xf<<12 | 0x1<<4
2613	case ADIVUHW:
2614		return o | 0x73<<20 | 0xf<<12 | 0x1<<4
2615	case AMMUL:
2616		return o | 0x75<<20 | 0xf<<12 | 0x1<<4
2617	case AMULS:
2618		return o | 0x6<<20 | 0x9<<4
2619	case AMMULA:
2620		return o | 0x75<<20 | 0x1<<4
2621	case AMMULS:
2622		return o | 0x75<<20 | 0xd<<4
2623	case AMULU, AMUL:
2624		return o | 0x0<<21 | 0x9<<4
2625	case AMULA:
2626		return o | 0x1<<21 | 0x9<<4
2627	case AMULLU:
2628		return o | 0x4<<21 | 0x9<<4
2629	case AMULL:
2630		return o | 0x6<<21 | 0x9<<4
2631	case AMULALU:
2632		return o | 0x5<<21 | 0x9<<4
2633	case AMULAL:
2634		return o | 0x7<<21 | 0x9<<4
2635	case AAND:
2636		return o | 0x0<<21
2637	case AEOR:
2638		return o | 0x1<<21
2639	case ASUB:
2640		return o | 0x2<<21
2641	case ARSB:
2642		return o | 0x3<<21
2643	case AADD:
2644		return o | 0x4<<21
2645	case AADC:
2646		return o | 0x5<<21
2647	case ASBC:
2648		return o | 0x6<<21
2649	case ARSC:
2650		return o | 0x7<<21
2651	case ATST:
2652		return o | 0x8<<21 | 1<<20
2653	case ATEQ:
2654		return o | 0x9<<21 | 1<<20
2655	case ACMP:
2656		return o | 0xa<<21 | 1<<20
2657	case ACMN:
2658		return o | 0xb<<21 | 1<<20
2659	case AORR:
2660		return o | 0xc<<21
2661
2662	case AMOVB, AMOVH, AMOVW:
2663		if sc&(C_PBIT|C_WBIT) != 0 {
2664			c.ctxt.Diag("invalid .P/.W suffix: %v", p)
2665		}
2666		return o | 0xd<<21
2667	case ABIC:
2668		return o | 0xe<<21
2669	case AMVN:
2670		return o | 0xf<<21
2671	case ASLL:
2672		return o | 0xd<<21 | 0<<5
2673	case ASRL:
2674		return o | 0xd<<21 | 1<<5
2675	case ASRA:
2676		return o | 0xd<<21 | 2<<5
2677	case ASWI:
2678		return o | 0xf<<24
2679
2680	case AADDD:
2681		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
2682	case AADDF:
2683		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
2684	case ASUBD:
2685		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
2686	case ASUBF:
2687		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
2688	case AMULD:
2689		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
2690	case AMULF:
2691		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
2692	case ANMULD:
2693		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
2694	case ANMULF:
2695		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
2696	case AMULAD:
2697		return o | 0xe<<24 | 0xb<<8
2698	case AMULAF:
2699		return o | 0xe<<24 | 0xa<<8
2700	case AMULSD:
2701		return o | 0xe<<24 | 0xb<<8 | 0x4<<4
2702	case AMULSF:
2703		return o | 0xe<<24 | 0xa<<8 | 0x4<<4
2704	case ANMULAD:
2705		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
2706	case ANMULAF:
2707		return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
2708	case ANMULSD:
2709		return o | 0xe<<24 | 0x1<<20 | 0xb<<8
2710	case ANMULSF:
2711		return o | 0xe<<24 | 0x1<<20 | 0xa<<8
2712	case AFMULAD:
2713		return o | 0xe<<24 | 0xa<<20 | 0xb<<8
2714	case AFMULAF:
2715		return o | 0xe<<24 | 0xa<<20 | 0xa<<8
2716	case AFMULSD:
2717		return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
2718	case AFMULSF:
2719		return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
2720	case AFNMULAD:
2721		return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
2722	case AFNMULAF:
2723		return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
2724	case AFNMULSD:
2725		return o | 0xe<<24 | 0x9<<20 | 0xb<<8
2726	case AFNMULSF:
2727		return o | 0xe<<24 | 0x9<<20 | 0xa<<8
2728	case ADIVD:
2729		return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
2730	case ADIVF:
2731		return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
2732	case ASQRTD:
2733		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
2734	case ASQRTF:
2735		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
2736	case AABSD:
2737		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
2738	case AABSF:
2739		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
2740	case ANEGD:
2741		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
2742	case ANEGF:
2743		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
2744	case ACMPD:
2745		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
2746	case ACMPF:
2747		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
2748
2749	case AMOVF:
2750		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
2751	case AMOVD:
2752		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
2753
2754	case AMOVDF:
2755		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
2756	case AMOVFD:
2757		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
2758
2759	case AMOVWF:
2760		if sc&C_UBIT == 0 {
2761			o |= 1 << 7 /* signed */
2762		}
2763		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
2764
2765	case AMOVWD:
2766		if sc&C_UBIT == 0 {
2767			o |= 1 << 7 /* signed */
2768		}
2769		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
2770
2771	case AMOVFW:
2772		if sc&C_UBIT == 0 {
2773			o |= 1 << 16 /* signed */
2774		}
2775		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
2776
2777	case AMOVDW:
2778		if sc&C_UBIT == 0 {
2779			o |= 1 << 16 /* signed */
2780		}
2781		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
2782
2783	case -AMOVWF: // copy WtoF
2784		return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
2785
2786	case -AMOVFW: // copy FtoW
2787		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
2788
2789	case -ACMP: // cmp imm
2790		return o | 0x3<<24 | 0x5<<20
2791
2792	case ABFX:
2793		return o | 0x3d<<21 | 0x5<<4
2794
2795	case ABFXU:
2796		return o | 0x3f<<21 | 0x5<<4
2797
2798	case ABFC:
2799		return o | 0x3e<<21 | 0x1f
2800
2801	case ABFI:
2802		return o | 0x3e<<21 | 0x1<<4
2803
2804	case AXTAB:
2805		return o | 0x6a<<20 | 0x7<<4
2806
2807	case AXTAH:
2808		return o | 0x6b<<20 | 0x7<<4
2809
2810	case AXTABU:
2811		return o | 0x6e<<20 | 0x7<<4
2812
2813	case AXTAHU:
2814		return o | 0x6f<<20 | 0x7<<4
2815
2816		// CLZ doesn't support .nil
2817	case ACLZ:
2818		return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
2819
2820	case AREV:
2821		return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
2822
2823	case AREV16:
2824		return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
2825
2826	case AREVSH:
2827		return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
2828
2829	case ARBIT:
2830		return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
2831
2832	case AMULWT:
2833		return o&(0xf<<28) | 0x12<<20 | 0xe<<4
2834
2835	case AMULWB:
2836		return o&(0xf<<28) | 0x12<<20 | 0xa<<4
2837
2838	case AMULBB:
2839		return o&(0xf<<28) | 0x16<<20 | 0x8<<4
2840
2841	case AMULAWT:
2842		return o&(0xf<<28) | 0x12<<20 | 0xc<<4
2843
2844	case AMULAWB:
2845		return o&(0xf<<28) | 0x12<<20 | 0x8<<4
2846
2847	case AMULABB:
2848		return o&(0xf<<28) | 0x10<<20 | 0x8<<4
2849
2850	case ABL: // BLX REG
2851		return o&(0xf<<28) | 0x12fff3<<4
2852	}
2853
2854	c.ctxt.Diag("%v: bad rrr %d", p, a)
2855	return 0
2856}
2857
2858func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
2859	sc &= C_SCOND
2860	sc ^= C_SCOND_XOR
2861	if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
2862		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
2863	}
2864	if sc != 0xe {
2865		c.ctxt.Diag("%v: .COND on bcond instruction", p)
2866	}
2867	switch a {
2868	case ABEQ:
2869		return 0x0<<28 | 0x5<<25
2870	case ABNE:
2871		return 0x1<<28 | 0x5<<25
2872	case ABCS:
2873		return 0x2<<28 | 0x5<<25
2874	case ABHS:
2875		return 0x2<<28 | 0x5<<25
2876	case ABCC:
2877		return 0x3<<28 | 0x5<<25
2878	case ABLO:
2879		return 0x3<<28 | 0x5<<25
2880	case ABMI:
2881		return 0x4<<28 | 0x5<<25
2882	case ABPL:
2883		return 0x5<<28 | 0x5<<25
2884	case ABVS:
2885		return 0x6<<28 | 0x5<<25
2886	case ABVC:
2887		return 0x7<<28 | 0x5<<25
2888	case ABHI:
2889		return 0x8<<28 | 0x5<<25
2890	case ABLS:
2891		return 0x9<<28 | 0x5<<25
2892	case ABGE:
2893		return 0xa<<28 | 0x5<<25
2894	case ABLT:
2895		return 0xb<<28 | 0x5<<25
2896	case ABGT:
2897		return 0xc<<28 | 0x5<<25
2898	case ABLE:
2899		return 0xd<<28 | 0x5<<25
2900	case AB:
2901		return 0xe<<28 | 0x5<<25
2902	}
2903
2904	c.ctxt.Diag("%v: bad bra %v", p, a)
2905	return 0
2906}
2907
2908func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
2909	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2910	if sc&C_PBIT == 0 {
2911		o |= 1 << 24
2912	}
2913	if sc&C_UBIT == 0 {
2914		o |= 1 << 23
2915	}
2916	if sc&C_WBIT != 0 {
2917		o |= 1 << 21
2918	}
2919	o |= 1<<26 | 1<<20
2920	if v < 0 {
2921		if sc&C_UBIT != 0 {
2922			c.ctxt.Diag(".U on neg offset")
2923		}
2924		v = -v
2925		o ^= 1 << 23
2926	}
2927
2928	if v >= 1<<12 || v < 0 {
2929		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2930	}
2931	o |= uint32(v)
2932	o |= (uint32(b) & 15) << 16
2933	o |= (uint32(r) & 15) << 12
2934	return o
2935}
2936
2937func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
2938	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2939	if sc&C_PBIT == 0 {
2940		o |= 1 << 24
2941	}
2942	if sc&C_WBIT != 0 {
2943		o |= 1 << 21
2944	}
2945	o |= 1<<23 | 1<<20 | 0xb<<4
2946	if v < 0 {
2947		v = -v
2948		o ^= 1 << 23
2949	}
2950
2951	if v >= 1<<8 || v < 0 {
2952		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2953	}
2954	o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
2955	o |= (uint32(b) & 15) << 16
2956	o |= (uint32(r) & 15) << 12
2957	return o
2958}
2959
2960func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
2961	o := c.olr(v, b, r, sc) ^ (1 << 20)
2962	if a != AMOVW {
2963		o |= 1 << 22
2964	}
2965	return o
2966}
2967
2968func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
2969	o := c.olhr(v, b, r, sc) ^ (1 << 20)
2970	return o
2971}
2972
2973func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
2974	return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
2975}
2976
2977func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
2978	return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
2979}
2980
2981func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
2982	return c.olr(int32(i), b, r, sc) ^ (1 << 25)
2983}
2984
2985func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
2986	return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
2987}
2988
2989func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
2990	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2991	if sc&C_PBIT == 0 {
2992		o |= 1 << 24
2993	}
2994	if sc&C_WBIT != 0 {
2995		o |= 1 << 21
2996	}
2997	o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
2998	if v < 0 {
2999		v = -v
3000		o ^= 1 << 23
3001	}
3002
3003	if v&3 != 0 {
3004		c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
3005	} else if v >= 1<<10 || v < 0 {
3006		c.ctxt.Diag("literal span too large: %d\n%v", v, p)
3007	}
3008	o |= (uint32(v) >> 2) & 0xFF
3009	o |= (uint32(b) & 15) << 16
3010	o |= (uint32(r) & 15) << 12
3011
3012	switch a {
3013	default:
3014		c.ctxt.Diag("bad fst %v", a)
3015		fallthrough
3016
3017	case AMOVD:
3018		o |= 1 << 8
3019		fallthrough
3020
3021	case AMOVF:
3022		break
3023	}
3024
3025	return o
3026}
3027
3028// MOVW $"lower 16-bit", Reg
3029func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3030	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
3031	o1 |= 0x30 << 20
3032	o1 |= (uint32(dr) & 15) << 12
3033	o1 |= uint32(a.Offset) & 0x0fff
3034	o1 |= (uint32(a.Offset) & 0xf000) << 4
3035	return o1
3036}
3037
3038// MVN $C_NCON, Reg -> MOVW $C_RCON, Reg
3039func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3040	o1 := c.oprrr(p, AMOVW, int(p.Scond))
3041	o1 |= (uint32(dr) & 15) << 12
3042	v := immrot(^uint32(a.Offset))
3043	if v == 0 {
3044		c.ctxt.Diag("%v: missing literal", p)
3045		return 0
3046	}
3047	o1 |= uint32(v)
3048	return o1
3049}
3050
3051func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3052	var o1 uint32
3053	if p.Pool == nil {
3054		c.aclass(a)
3055		v := immrot(^uint32(c.instoffset))
3056		if v == 0 {
3057			c.ctxt.Diag("%v: missing literal", p)
3058			return 0
3059		}
3060
3061		o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
3062		o1 |= uint32(v)
3063		o1 |= (uint32(dr) & 15) << 12
3064	} else {
3065		v := int32(p.Pool.Pc - p.Pc - 8)
3066		o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
3067	}
3068
3069	return o1
3070}
3071
3072func (c *ctxt5) chipzero5(e float64) int {
3073	// We use GOARM.Version=7 and !GOARM.SoftFloat to gate the use of VFPv3 vmov (imm) instructions.
3074	if buildcfg.GOARM.Version < 7 || buildcfg.GOARM.SoftFloat || math.Float64bits(e) != 0 {
3075		return -1
3076	}
3077	return 0
3078}
3079
3080func (c *ctxt5) chipfloat5(e float64) int {
3081	// We use GOARM.Version=7 and !GOARM.SoftFloat to gate the use of VFPv3 vmov (imm) instructions.
3082	if buildcfg.GOARM.Version < 7 || buildcfg.GOARM.SoftFloat {
3083		return -1
3084	}
3085
3086	ei := math.Float64bits(e)
3087	l := uint32(ei)
3088	h := uint32(ei >> 32)
3089
3090	if l != 0 || h&0xffff != 0 {
3091		return -1
3092	}
3093	h1 := h & 0x7fc00000
3094	if h1 != 0x40000000 && h1 != 0x3fc00000 {
3095		return -1
3096	}
3097	n := 0
3098
3099	// sign bit (a)
3100	if h&0x80000000 != 0 {
3101		n |= 1 << 7
3102	}
3103
3104	// exp sign bit (b)
3105	if h1 == 0x3fc00000 {
3106		n |= 1 << 6
3107	}
3108
3109	// rest of exp and mantissa (cd-efgh)
3110	n |= int((h >> 16) & 0x3f)
3111
3112	//print("match %.8lux %.8lux %d\n", l, h, n);
3113	return n
3114}
3115
3116func nocache(p *obj.Prog) {
3117	p.Optab = 0
3118	p.From.Class = 0
3119	if p.GetFrom3() != nil {
3120		p.GetFrom3().Class = 0
3121	}
3122	p.To.Class = 0
3123}
3124