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 (forsyth@terzarima.net)
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 (forsyth@terzarima.net)
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_SROREG,
692		C_LOREG,
693		C_ROREG,
694		C_FOREG,
695		C_SOREG,
696		C_HOREG,
697		C_FAUTO,
698		C_SAUTO,
699		C_LAUTO,
700		C_LACON:
701		t.To.Type = obj.TYPE_CONST
702		t.To.Offset = c.instoffset
703	}
704
705	if t.Rel == nil {
706		for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
707			if q.Rel == nil && q.To == t.To {
708				p.Pool = q
709				return
710			}
711		}
712	}
713
714	q := c.newprog()
715	*q = *t
716	q.Pc = int64(c.pool.size)
717
718	if c.blitrl == nil {
719		c.blitrl = q
720		c.pool.start = uint32(p.Pc)
721	} else {
722		c.elitrl.Link = q
723	}
724	c.elitrl = q
725	c.pool.size += 4
726
727	// Store the link to the pool entry in Pool.
728	p.Pool = q
729}
730
731func (c *ctxt5) regoff(a *obj.Addr) int32 {
732	c.instoffset = 0
733	c.aclass(a)
734	return int32(c.instoffset)
735}
736
737func immrot(v uint32) int32 {
738	for i := 0; i < 16; i++ {
739		if v&^0xff == 0 {
740			return int32(uint32(int32(i)<<8) | v | 1<<25)
741		}
742		v = v<<2 | v>>30
743	}
744
745	return 0
746}
747
748// immrot2a returns bits encoding the immediate constant fields of two instructions,
749// such that the encoded constants x, y satisfy x|y==v, x&y==0.
750// Returns 0,0 if no such decomposition of v exists.
751func immrot2a(v uint32) (uint32, uint32) {
752	for i := uint(1); i < 32; i++ {
753		m := uint32(1<<i - 1)
754		if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 {
755			return uint32(x), uint32(y)
756		}
757	}
758	// TODO: handle some more cases, like where
759	// the wraparound from the rotate could help.
760	return 0, 0
761}
762
763// immrot2s returns bits encoding the immediate constant fields of two instructions,
764// such that the encoded constants y, x satisfy y-x==v, y&x==0.
765// Returns 0,0 if no such decomposition of v exists.
766func immrot2s(v uint32) (uint32, uint32) {
767	if immrot(v) != 0 {
768		return v, 0
769	}
770	// suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
771	// omit trailing 00
772	var i uint32
773	for i = 2; i < 32; i += 2 {
774		if v&(1<<i-1) != 0 {
775			break
776		}
777	}
778	// i must be <= 24, then adjust i just above lower 8 effective bits of v
779	i += 6
780	// let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
781	x := 1<<i - v&(1<<i-1)
782	y := v + x
783	if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 {
784		return y, x
785	}
786	return 0, 0
787}
788
789func immaddr(v int32) int32 {
790	if v >= 0 && v <= 0xfff {
791		return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
792	}
793	if v >= -0xfff && v < 0 {
794		return -v&0xfff | 1<<24 /* pre indexing */
795	}
796	return 0
797}
798
799func immfloat(v int32) bool {
800	return v&0xC03 == 0 /* offset will fit in floating-point load/store */
801}
802
803func immhalf(v int32) bool {
804	if v >= 0 && v <= 0xff {
805		return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
806	}
807	if v >= -0xff && v < 0 {
808		return -v&0xff|1<<24 != 0 /* pre indexing */
809	}
810	return false
811}
812
813func (c *ctxt5) aclass(a *obj.Addr) int {
814	switch a.Type {
815	case obj.TYPE_NONE:
816		return C_NONE
817
818	case obj.TYPE_REG:
819		c.instoffset = 0
820		if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
821			return C_REG
822		}
823		if REG_F0 <= a.Reg && a.Reg <= REG_F15 {
824			return C_FREG
825		}
826		if a.Reg == REG_FPSR || a.Reg == REG_FPCR {
827			return C_FCR
828		}
829		if a.Reg == REG_CPSR || a.Reg == REG_SPSR {
830			return C_PSR
831		}
832		if a.Reg >= REG_SPECIAL {
833			return C_SPR
834		}
835		return C_GOK
836
837	case obj.TYPE_REGREG:
838		return C_REGREG
839
840	case obj.TYPE_REGREG2:
841		return C_REGREG2
842
843	case obj.TYPE_REGLIST:
844		return C_REGLIST
845
846	case obj.TYPE_SHIFT:
847		if a.Reg == 0 {
848			// register shift R>>i
849			return C_SHIFT
850		} else {
851			// memory address with shifted offset R>>i(R)
852			return C_SHIFTADDR
853		}
854
855	case obj.TYPE_MEM:
856		switch a.Name {
857		case obj.NAME_EXTERN,
858			obj.NAME_GOTREF,
859			obj.NAME_STATIC:
860			if a.Sym == nil || a.Sym.Name == "" {
861				fmt.Printf("null sym external\n")
862				return C_GOK
863			}
864
865			c.instoffset = 0 // s.b. unused but just in case
866			if a.Sym.Type == objabi.STLSBSS {
867				if c.ctxt.Flag_shared {
868					return C_TLS_IE
869				} else {
870					return C_TLS_LE
871				}
872			}
873
874			return C_ADDR
875
876		case obj.NAME_AUTO:
877			if a.Reg == REGSP {
878				// unset base register for better printing, since
879				// a.Offset is still relative to pseudo-SP.
880				a.Reg = obj.REG_NONE
881			}
882			c.instoffset = c.autosize + a.Offset
883			if t := immaddr(int32(c.instoffset)); t != 0 {
884				if immhalf(int32(c.instoffset)) {
885					if immfloat(t) {
886						return C_HFAUTO
887					}
888					return C_HAUTO
889				}
890
891				if immfloat(t) {
892					return C_FAUTO
893				}
894				return C_SAUTO
895			}
896
897			return C_LAUTO
898
899		case obj.NAME_PARAM:
900			if a.Reg == REGSP {
901				// unset base register for better printing, since
902				// a.Offset is still relative to pseudo-FP.
903				a.Reg = obj.REG_NONE
904			}
905			c.instoffset = c.autosize + a.Offset + 4
906			if t := immaddr(int32(c.instoffset)); t != 0 {
907				if immhalf(int32(c.instoffset)) {
908					if immfloat(t) {
909						return C_HFAUTO
910					}
911					return C_HAUTO
912				}
913
914				if immfloat(t) {
915					return C_FAUTO
916				}
917				return C_SAUTO
918			}
919
920			return C_LAUTO
921
922		case obj.NAME_NONE:
923			c.instoffset = a.Offset
924			if t := immaddr(int32(c.instoffset)); t != 0 {
925				if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
926					if immfloat(t) {
927						return C_HFOREG
928					}
929					return C_HOREG
930				}
931
932				if immfloat(t) {
933					return C_FOREG /* n.b. that it will also satisfy immrot */
934				}
935				if immrot(uint32(c.instoffset)) != 0 {
936					return C_SROREG
937				}
938				if immhalf(int32(c.instoffset)) {
939					return C_HOREG
940				}
941				return C_SOREG
942			}
943
944			if immrot(uint32(c.instoffset)) != 0 {
945				return C_ROREG
946			}
947			return C_LOREG
948		}
949
950		return C_GOK
951
952	case obj.TYPE_FCONST:
953		if c.chipzero5(a.Val.(float64)) >= 0 {
954			return C_ZFCON
955		}
956		if c.chipfloat5(a.Val.(float64)) >= 0 {
957			return C_SFCON
958		}
959		return C_LFCON
960
961	case obj.TYPE_TEXTSIZE:
962		return C_TEXTSIZE
963
964	case obj.TYPE_CONST,
965		obj.TYPE_ADDR:
966		switch a.Name {
967		case obj.NAME_NONE:
968			c.instoffset = a.Offset
969			if a.Reg != 0 {
970				return c.aconsize()
971			}
972
973			if immrot(uint32(c.instoffset)) != 0 {
974				return C_RCON
975			}
976			if immrot(^uint32(c.instoffset)) != 0 {
977				return C_NCON
978			}
979			if uint32(c.instoffset) <= 0xffff && buildcfg.GOARM == 7 {
980				return C_SCON
981			}
982			if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
983				return C_RCON2A
984			}
985			if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
986				return C_RCON2S
987			}
988			return C_LCON
989
990		case obj.NAME_EXTERN,
991			obj.NAME_GOTREF,
992			obj.NAME_STATIC:
993			s := a.Sym
994			if s == nil {
995				break
996			}
997			c.instoffset = 0 // s.b. unused but just in case
998			return C_LCONADDR
999
1000		case obj.NAME_AUTO:
1001			if a.Reg == REGSP {
1002				// unset base register for better printing, since
1003				// a.Offset is still relative to pseudo-SP.
1004				a.Reg = obj.REG_NONE
1005			}
1006			c.instoffset = c.autosize + a.Offset
1007			return c.aconsize()
1008
1009		case obj.NAME_PARAM:
1010			if a.Reg == REGSP {
1011				// unset base register for better printing, since
1012				// a.Offset is still relative to pseudo-FP.
1013				a.Reg = obj.REG_NONE
1014			}
1015			c.instoffset = c.autosize + a.Offset + 4
1016			return c.aconsize()
1017		}
1018
1019		return C_GOK
1020
1021	case obj.TYPE_BRANCH:
1022		return C_SBRA
1023	}
1024
1025	return C_GOK
1026}
1027
1028func (c *ctxt5) aconsize() int {
1029	if immrot(uint32(c.instoffset)) != 0 {
1030		return C_RACON
1031	}
1032	if immrot(uint32(-c.instoffset)) != 0 {
1033		return C_RACON
1034	}
1035	return C_LACON
1036}
1037
1038func (c *ctxt5) oplook(p *obj.Prog) *Optab {
1039	a1 := int(p.Optab)
1040	if a1 != 0 {
1041		return &optab[a1-1]
1042	}
1043	a1 = int(p.From.Class)
1044	if a1 == 0 {
1045		a1 = c.aclass(&p.From) + 1
1046		p.From.Class = int8(a1)
1047	}
1048
1049	a1--
1050	a3 := int(p.To.Class)
1051	if a3 == 0 {
1052		a3 = c.aclass(&p.To) + 1
1053		p.To.Class = int8(a3)
1054	}
1055
1056	a3--
1057	a2 := C_NONE
1058	if p.Reg != 0 {
1059		switch {
1060		case REG_F0 <= p.Reg && p.Reg <= REG_F15:
1061			a2 = C_FREG
1062		case REG_R0 <= p.Reg && p.Reg <= REG_R15:
1063			a2 = C_REG
1064		default:
1065			c.ctxt.Diag("invalid register in %v", p)
1066		}
1067	}
1068
1069	// check illegal base register
1070	switch a1 {
1071	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
1072		if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
1073			c.ctxt.Diag("illegal base register: %v", p)
1074		}
1075	default:
1076	}
1077	switch a3 {
1078	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
1079		if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
1080			c.ctxt.Diag("illegal base register: %v", p)
1081		}
1082	default:
1083	}
1084
1085	// If current instruction has a .S suffix (flags update),
1086	// we must use the constant pool instead of splitting it.
1087	if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
1088		a1 = C_LCON
1089	}
1090	if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
1091		a3 = C_LCON
1092	}
1093
1094	if false { /*debug['O']*/
1095		fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
1096		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
1097	}
1098
1099	ops := oprange[p.As&obj.AMask]
1100	c1 := &xcmp[a1]
1101	c3 := &xcmp[a3]
1102	for i := range ops {
1103		op := &ops[i]
1104		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
1105			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
1106			checkSuffix(c, p, op)
1107			return op
1108		}
1109	}
1110
1111	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)
1112	if ops == nil {
1113		ops = optab
1114	}
1115	return &ops[0]
1116}
1117
1118func cmp(a int, b int) bool {
1119	if a == b {
1120		return true
1121	}
1122	switch a {
1123	case C_LCON:
1124		if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
1125			return true
1126		}
1127
1128	case C_LACON:
1129		if b == C_RACON {
1130			return true
1131		}
1132
1133	case C_LFCON:
1134		if b == C_ZFCON || b == C_SFCON {
1135			return true
1136		}
1137
1138	case C_HFAUTO:
1139		return b == C_HAUTO || b == C_FAUTO
1140
1141	case C_FAUTO, C_HAUTO:
1142		return b == C_HFAUTO
1143
1144	case C_SAUTO:
1145		return cmp(C_HFAUTO, b)
1146
1147	case C_LAUTO:
1148		return cmp(C_SAUTO, b)
1149
1150	case C_HFOREG:
1151		return b == C_HOREG || b == C_FOREG
1152
1153	case C_FOREG, C_HOREG:
1154		return b == C_HFOREG
1155
1156	case C_SROREG:
1157		return cmp(C_SOREG, b) || cmp(C_ROREG, b)
1158
1159	case C_SOREG, C_ROREG:
1160		return b == C_SROREG || cmp(C_HFOREG, b)
1161
1162	case C_LOREG:
1163		return cmp(C_SROREG, b)
1164
1165	case C_LBRA:
1166		if b == C_SBRA {
1167			return true
1168		}
1169
1170	case C_HREG:
1171		return cmp(C_SP, b) || cmp(C_PC, b)
1172	}
1173
1174	return false
1175}
1176
1177type ocmp []Optab
1178
1179func (x ocmp) Len() int {
1180	return len(x)
1181}
1182
1183func (x ocmp) Swap(i, j int) {
1184	x[i], x[j] = x[j], x[i]
1185}
1186
1187func (x ocmp) Less(i, j int) bool {
1188	p1 := &x[i]
1189	p2 := &x[j]
1190	n := int(p1.as) - int(p2.as)
1191	if n != 0 {
1192		return n < 0
1193	}
1194	n = int(p1.a1) - int(p2.a1)
1195	if n != 0 {
1196		return n < 0
1197	}
1198	n = int(p1.a2) - int(p2.a2)
1199	if n != 0 {
1200		return n < 0
1201	}
1202	n = int(p1.a3) - int(p2.a3)
1203	if n != 0 {
1204		return n < 0
1205	}
1206	return false
1207}
1208
1209func opset(a, b0 obj.As) {
1210	oprange[a&obj.AMask] = oprange[b0]
1211}
1212
1213func buildop(ctxt *obj.Link) {
1214	if oprange[AAND&obj.AMask] != nil {
1215		// Already initialized; stop now.
1216		// This happens in the cmd/asm tests,
1217		// each of which re-initializes the arch.
1218		return
1219	}
1220
1221	symdiv = ctxt.Lookup("runtime._div")
1222	symdivu = ctxt.Lookup("runtime._divu")
1223	symmod = ctxt.Lookup("runtime._mod")
1224	symmodu = ctxt.Lookup("runtime._modu")
1225
1226	var n int
1227
1228	for i := 0; i < C_GOK; i++ {
1229		for n = 0; n < C_GOK; n++ {
1230			if cmp(n, i) {
1231				xcmp[i][n] = true
1232			}
1233		}
1234	}
1235	for n = 0; optab[n].as != obj.AXXX; n++ {
1236		if optab[n].flag&LPCREL != 0 {
1237			if ctxt.Flag_shared {
1238				optab[n].size += int8(optab[n].pcrelsiz)
1239			} else {
1240				optab[n].flag &^= LPCREL
1241			}
1242		}
1243	}
1244
1245	sort.Sort(ocmp(optab[:n]))
1246	for i := 0; i < n; i++ {
1247		r := optab[i].as
1248		r0 := r & obj.AMask
1249		start := i
1250		for optab[i].as == r {
1251			i++
1252		}
1253		oprange[r0] = optab[start:i]
1254		i--
1255
1256		switch r {
1257		default:
1258			ctxt.Diag("unknown op in build: %v", r)
1259			ctxt.DiagFlush()
1260			log.Fatalf("bad code")
1261
1262		case AADD:
1263			opset(ASUB, r0)
1264			opset(ARSB, r0)
1265			opset(AADC, r0)
1266			opset(ASBC, r0)
1267			opset(ARSC, r0)
1268
1269		case AORR:
1270			opset(AEOR, r0)
1271			opset(ABIC, r0)
1272
1273		case ACMP:
1274			opset(ATEQ, r0)
1275			opset(ACMN, r0)
1276			opset(ATST, r0)
1277
1278		case AMVN:
1279			break
1280
1281		case ABEQ:
1282			opset(ABNE, r0)
1283			opset(ABCS, r0)
1284			opset(ABHS, r0)
1285			opset(ABCC, r0)
1286			opset(ABLO, r0)
1287			opset(ABMI, r0)
1288			opset(ABPL, r0)
1289			opset(ABVS, r0)
1290			opset(ABVC, r0)
1291			opset(ABHI, r0)
1292			opset(ABLS, r0)
1293			opset(ABGE, r0)
1294			opset(ABLT, r0)
1295			opset(ABGT, r0)
1296			opset(ABLE, r0)
1297
1298		case ASLL:
1299			opset(ASRL, r0)
1300			opset(ASRA, r0)
1301
1302		case AMUL:
1303			opset(AMULU, r0)
1304
1305		case ADIV:
1306			opset(AMOD, r0)
1307			opset(AMODU, r0)
1308			opset(ADIVU, r0)
1309
1310		case ADIVHW:
1311			opset(ADIVUHW, r0)
1312
1313		case AMOVW,
1314			AMOVB,
1315			AMOVBS,
1316			AMOVBU,
1317			AMOVH,
1318			AMOVHS,
1319			AMOVHU:
1320			break
1321
1322		case ASWPW:
1323			opset(ASWPBU, r0)
1324
1325		case AB,
1326			ABL,
1327			ABX,
1328			ABXRET,
1329			obj.ADUFFZERO,
1330			obj.ADUFFCOPY,
1331			ASWI,
1332			AWORD,
1333			AMOVM,
1334			ARFE,
1335			obj.ATEXT:
1336			break
1337
1338		case AADDF:
1339			opset(AADDD, r0)
1340			opset(ASUBF, r0)
1341			opset(ASUBD, r0)
1342			opset(AMULF, r0)
1343			opset(AMULD, r0)
1344			opset(ANMULF, r0)
1345			opset(ANMULD, r0)
1346			opset(AMULAF, r0)
1347			opset(AMULAD, r0)
1348			opset(AMULSF, r0)
1349			opset(AMULSD, r0)
1350			opset(ANMULAF, r0)
1351			opset(ANMULAD, r0)
1352			opset(ANMULSF, r0)
1353			opset(ANMULSD, r0)
1354			opset(AFMULAF, r0)
1355			opset(AFMULAD, r0)
1356			opset(AFMULSF, r0)
1357			opset(AFMULSD, r0)
1358			opset(AFNMULAF, r0)
1359			opset(AFNMULAD, r0)
1360			opset(AFNMULSF, r0)
1361			opset(AFNMULSD, r0)
1362			opset(ADIVF, r0)
1363			opset(ADIVD, r0)
1364
1365		case ANEGF:
1366			opset(ANEGD, r0)
1367			opset(ASQRTF, r0)
1368			opset(ASQRTD, r0)
1369			opset(AMOVFD, r0)
1370			opset(AMOVDF, r0)
1371			opset(AABSF, r0)
1372			opset(AABSD, r0)
1373
1374		case ACMPF:
1375			opset(ACMPD, r0)
1376
1377		case AMOVF:
1378			opset(AMOVD, r0)
1379
1380		case AMOVFW:
1381			opset(AMOVDW, r0)
1382
1383		case AMOVWF:
1384			opset(AMOVWD, r0)
1385
1386		case AMULL:
1387			opset(AMULAL, r0)
1388			opset(AMULLU, r0)
1389			opset(AMULALU, r0)
1390
1391		case AMULWT:
1392			opset(AMULWB, r0)
1393			opset(AMULBB, r0)
1394			opset(AMMUL, r0)
1395
1396		case AMULAWT:
1397			opset(AMULAWB, r0)
1398			opset(AMULABB, r0)
1399			opset(AMULS, r0)
1400			opset(AMMULA, r0)
1401			opset(AMMULS, r0)
1402
1403		case ABFX:
1404			opset(ABFXU, r0)
1405			opset(ABFC, r0)
1406			opset(ABFI, r0)
1407
1408		case ACLZ:
1409			opset(AREV, r0)
1410			opset(AREV16, r0)
1411			opset(AREVSH, r0)
1412			opset(ARBIT, r0)
1413
1414		case AXTAB:
1415			opset(AXTAH, r0)
1416			opset(AXTABU, r0)
1417			opset(AXTAHU, r0)
1418
1419		case ALDREX,
1420			ASTREX,
1421			ALDREXD,
1422			ASTREXD,
1423			ADMB,
1424			APLD,
1425			AAND,
1426			AMULA,
1427			obj.AUNDEF,
1428			obj.AFUNCDATA,
1429			obj.APCDATA,
1430			obj.ANOP:
1431			break
1432		}
1433	}
1434}
1435
1436func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
1437	c.printp = p
1438	o1 := uint32(0)
1439	o2 := uint32(0)
1440	o3 := uint32(0)
1441	o4 := uint32(0)
1442	o5 := uint32(0)
1443	o6 := uint32(0)
1444	if false { /*debug['P']*/
1445		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
1446	}
1447	switch o.type_ {
1448	default:
1449		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
1450
1451	case 0: /* pseudo ops */
1452		if false { /*debug['G']*/
1453			fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
1454		}
1455
1456	case 1: /* op R,[R],R */
1457		o1 = c.oprrr(p, p.As, int(p.Scond))
1458
1459		rf := int(p.From.Reg)
1460		rt := int(p.To.Reg)
1461		r := int(p.Reg)
1462		if p.To.Type == obj.TYPE_NONE {
1463			rt = 0
1464		}
1465		if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
1466			r = 0
1467		} else if r == 0 {
1468			r = rt
1469		}
1470		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1471
1472	case 2: /* movbu $I,[R],R */
1473		c.aclass(&p.From)
1474
1475		o1 = c.oprrr(p, p.As, int(p.Scond))
1476		o1 |= uint32(immrot(uint32(c.instoffset)))
1477		rt := int(p.To.Reg)
1478		r := int(p.Reg)
1479		if p.To.Type == obj.TYPE_NONE {
1480			rt = 0
1481		}
1482		if p.As == AMOVW || p.As == AMVN {
1483			r = 0
1484		} else if r == 0 {
1485			r = rt
1486		}
1487		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1488
1489	case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
1490		c.aclass(&p.From)
1491		r := int(p.Reg)
1492		rt := int(p.To.Reg)
1493		if r == 0 {
1494			r = rt
1495		}
1496		x, y := immrot2a(uint32(c.instoffset))
1497		var as2 obj.As
1498		switch p.As {
1499		case AADD, ASUB, AORR, AEOR, ABIC:
1500			as2 = p.As // ADD, SUB, ORR, EOR, BIC
1501		case ARSB:
1502			as2 = AADD // RSB -> RSB/ADD pair
1503		case AADC:
1504			as2 = AADD // ADC -> ADC/ADD pair
1505		case ASBC:
1506			as2 = ASUB // SBC -> SBC/SUB pair
1507		case ARSC:
1508			as2 = AADD // RSC -> RSC/ADD pair
1509		default:
1510			c.ctxt.Diag("unknown second op for %v", p)
1511		}
1512		o1 = c.oprrr(p, p.As, int(p.Scond))
1513		o2 = c.oprrr(p, as2, int(p.Scond))
1514		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1515		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1516		o1 |= x
1517		o2 |= y
1518
1519	case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
1520		c.aclass(&p.From)
1521		r := int(p.Reg)
1522		rt := int(p.To.Reg)
1523		if r == 0 {
1524			r = rt
1525		}
1526		y, x := immrot2s(uint32(c.instoffset))
1527		var as2 obj.As
1528		switch p.As {
1529		case AADD:
1530			as2 = ASUB // ADD -> ADD/SUB pair
1531		case ASUB:
1532			as2 = AADD // SUB -> SUB/ADD pair
1533		case ARSB:
1534			as2 = ASUB // RSB -> RSB/SUB pair
1535		case AADC:
1536			as2 = ASUB // ADC -> ADC/SUB pair
1537		case ASBC:
1538			as2 = AADD // SBC -> SBC/ADD pair
1539		case ARSC:
1540			as2 = ASUB // RSC -> RSC/SUB pair
1541		default:
1542			c.ctxt.Diag("unknown second op for %v", p)
1543		}
1544		o1 = c.oprrr(p, p.As, int(p.Scond))
1545		o2 = c.oprrr(p, as2, int(p.Scond))
1546		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1547		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1548		o1 |= y
1549		o2 |= x
1550
1551	case 3: /* add R<<[IR],[R],R */
1552		o1 = c.mov(p)
1553
1554	case 4: /* MOVW $off(R), R -> add $off,[R],R */
1555		c.aclass(&p.From)
1556		if c.instoffset < 0 {
1557			o1 = c.oprrr(p, ASUB, int(p.Scond))
1558			o1 |= uint32(immrot(uint32(-c.instoffset)))
1559		} else {
1560			o1 = c.oprrr(p, AADD, int(p.Scond))
1561			o1 |= uint32(immrot(uint32(c.instoffset)))
1562		}
1563		r := int(p.From.Reg)
1564		if r == 0 {
1565			r = int(o.param)
1566		}
1567		o1 |= (uint32(r) & 15) << 16
1568		o1 |= (uint32(p.To.Reg) & 15) << 12
1569
1570	case 5: /* bra s */
1571		o1 = c.opbra(p, p.As, int(p.Scond))
1572
1573		v := int32(-8)
1574		if p.To.Sym != nil {
1575			rel := obj.Addrel(c.cursym)
1576			rel.Off = int32(c.pc)
1577			rel.Siz = 4
1578			rel.Sym = p.To.Sym
1579			v += int32(p.To.Offset)
1580			rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
1581			rel.Type = objabi.R_CALLARM
1582			break
1583		}
1584
1585		if p.To.Target() != nil {
1586			v = int32((p.To.Target().Pc - c.pc) - 8)
1587		}
1588		o1 |= (uint32(v) >> 2) & 0xffffff
1589
1590	case 6: /* b ,O(R) -> add $O,R,PC */
1591		c.aclass(&p.To)
1592
1593		o1 = c.oprrr(p, AADD, int(p.Scond))
1594		o1 |= uint32(immrot(uint32(c.instoffset)))
1595		o1 |= (uint32(p.To.Reg) & 15) << 16
1596		o1 |= (REGPC & 15) << 12
1597
1598	case 7: /* bl (R) -> blx R */
1599		c.aclass(&p.To)
1600
1601		if c.instoffset != 0 {
1602			c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
1603		}
1604		o1 = c.oprrr(p, ABL, int(p.Scond))
1605		o1 |= (uint32(p.To.Reg) & 15) << 0
1606		rel := obj.Addrel(c.cursym)
1607		rel.Off = int32(c.pc)
1608		rel.Siz = 0
1609		rel.Type = objabi.R_CALLIND
1610
1611	case 8: /* sll $c,[R],R -> mov (R<<$c),R */
1612		c.aclass(&p.From)
1613
1614		o1 = c.oprrr(p, p.As, int(p.Scond))
1615		r := int(p.Reg)
1616		if r == 0 {
1617			r = int(p.To.Reg)
1618		}
1619		o1 |= (uint32(r) & 15) << 0
1620		o1 |= uint32((c.instoffset & 31) << 7)
1621		o1 |= (uint32(p.To.Reg) & 15) << 12
1622
1623	case 9: /* sll R,[R],R -> mov (R<<R),R */
1624		o1 = c.oprrr(p, p.As, int(p.Scond))
1625
1626		r := int(p.Reg)
1627		if r == 0 {
1628			r = int(p.To.Reg)
1629		}
1630		o1 |= (uint32(r) & 15) << 0
1631		o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
1632		o1 |= (uint32(p.To.Reg) & 15) << 12
1633
1634	case 10: /* swi [$con] */
1635		o1 = c.oprrr(p, p.As, int(p.Scond))
1636
1637		if p.To.Type != obj.TYPE_NONE {
1638			c.aclass(&p.To)
1639			o1 |= uint32(c.instoffset & 0xffffff)
1640		}
1641
1642	case 11: /* word */
1643		c.aclass(&p.To)
1644
1645		o1 = uint32(c.instoffset)
1646		if p.To.Sym != nil {
1647			// This case happens with words generated
1648			// in the PC stream as part of the literal pool (c.pool).
1649			rel := obj.Addrel(c.cursym)
1650
1651			rel.Off = int32(c.pc)
1652			rel.Siz = 4
1653			rel.Sym = p.To.Sym
1654			rel.Add = p.To.Offset
1655
1656			if c.ctxt.Flag_shared {
1657				if p.To.Name == obj.NAME_GOTREF {
1658					rel.Type = objabi.R_GOTPCREL
1659				} else {
1660					rel.Type = objabi.R_PCREL
1661				}
1662				rel.Add += c.pc - p.Rel.Pc - 8
1663			} else {
1664				rel.Type = objabi.R_ADDR
1665			}
1666			o1 = 0
1667		}
1668
1669	case 12: /* movw $lcon, reg */
1670		if o.a1 == C_SCON {
1671			o1 = c.omvs(p, &p.From, int(p.To.Reg))
1672		} else if p.As == AMVN {
1673			o1 = c.omvr(p, &p.From, int(p.To.Reg))
1674		} else {
1675			o1 = c.omvl(p, &p.From, int(p.To.Reg))
1676		}
1677
1678		if o.flag&LPCREL != 0 {
1679			o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
1680		}
1681
1682	case 13: /* op $lcon, [R], R */
1683		if o.a1 == C_SCON {
1684			o1 = c.omvs(p, &p.From, REGTMP)
1685		} else {
1686			o1 = c.omvl(p, &p.From, REGTMP)
1687		}
1688
1689		if o1 == 0 {
1690			break
1691		}
1692		o2 = c.oprrr(p, p.As, int(p.Scond))
1693		o2 |= REGTMP & 15
1694		r := int(p.Reg)
1695		if p.As == AMVN {
1696			r = 0
1697		} else if r == 0 {
1698			r = int(p.To.Reg)
1699		}
1700		o2 |= (uint32(r) & 15) << 16
1701		if p.To.Type != obj.TYPE_NONE {
1702			o2 |= (uint32(p.To.Reg) & 15) << 12
1703		}
1704
1705	case 14: /* movb/movbu/movh/movhu R,R */
1706		o1 = c.oprrr(p, ASLL, int(p.Scond))
1707
1708		if p.As == AMOVBU || p.As == AMOVHU {
1709			o2 = c.oprrr(p, ASRL, int(p.Scond))
1710		} else {
1711			o2 = c.oprrr(p, ASRA, int(p.Scond))
1712		}
1713
1714		r := int(p.To.Reg)
1715		o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
1716		o2 |= uint32(r)&15 | (uint32(r)&15)<<12
1717		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
1718			o1 |= 24 << 7
1719			o2 |= 24 << 7
1720		} else {
1721			o1 |= 16 << 7
1722			o2 |= 16 << 7
1723		}
1724
1725	case 15: /* mul r,[r,]r */
1726		o1 = c.oprrr(p, p.As, int(p.Scond))
1727
1728		rf := int(p.From.Reg)
1729		rt := int(p.To.Reg)
1730		r := int(p.Reg)
1731		if r == 0 {
1732			r = rt
1733		}
1734
1735		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
1736
1737	case 16: /* div r,[r,]r */
1738		o1 = 0xf << 28
1739
1740		o2 = 0
1741
1742	case 17:
1743		o1 = c.oprrr(p, p.As, int(p.Scond))
1744		rf := int(p.From.Reg)
1745		rt := int(p.To.Reg)
1746		rt2 := int(p.To.Offset)
1747		r := int(p.Reg)
1748		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
1749
1750	case 18: /* BFX/BFXU/BFC/BFI */
1751		o1 = c.oprrr(p, p.As, int(p.Scond))
1752		rt := int(p.To.Reg)
1753		r := int(p.Reg)
1754		if r == 0 {
1755			r = rt
1756		} else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0
1757			c.ctxt.Diag("illegal combination: %v", p)
1758		}
1759		if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
1760			c.ctxt.Diag("%v: missing or wrong LSB", p)
1761			break
1762		}
1763		lsb := p.GetFrom3().Offset
1764		width := p.From.Offset
1765		if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
1766			c.ctxt.Diag("%v: wrong width or LSB", p)
1767		}
1768		switch p.As {
1769		case ABFX, ABFXU: // (width-1) is encoded
1770			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
1771		case ABFC, ABFI: // MSB is encoded
1772			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
1773		default:
1774			c.ctxt.Diag("illegal combination: %v", p)
1775		}
1776
1777	case 20: /* mov/movb/movbu R,O(R) */
1778		c.aclass(&p.To)
1779
1780		r := int(p.To.Reg)
1781		if r == 0 {
1782			r = int(o.param)
1783		}
1784		o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
1785
1786	case 21: /* mov/movbu O(R),R -> lr */
1787		c.aclass(&p.From)
1788
1789		r := int(p.From.Reg)
1790		if r == 0 {
1791			r = int(o.param)
1792		}
1793		o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
1794		if p.As != AMOVW {
1795			o1 |= 1 << 22
1796		}
1797
1798	case 22: /* XTAB R@>i, [R], R */
1799		o1 = c.oprrr(p, p.As, int(p.Scond))
1800		switch p.From.Offset &^ 0xf {
1801		// only 0/8/16/24 bits rotation is accepted
1802		case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
1803			o1 |= uint32(p.From.Offset) & 0xc0f
1804		default:
1805			c.ctxt.Diag("illegal shift: %v", p)
1806		}
1807		rt := p.To.Reg
1808		r := p.Reg
1809		if r == 0 {
1810			r = rt
1811		}
1812		o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
1813
1814	case 23: /* MOVW/MOVB/MOVH R@>i, R */
1815		switch p.As {
1816		case AMOVW:
1817			o1 = c.mov(p)
1818		case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
1819			o1 = c.movxt(p)
1820		default:
1821			c.ctxt.Diag("illegal combination: %v", p)
1822		}
1823
1824	case 30: /* mov/movb/movbu R,L(R) */
1825		o1 = c.omvl(p, &p.To, REGTMP)
1826
1827		if o1 == 0 {
1828			break
1829		}
1830		r := int(p.To.Reg)
1831		if r == 0 {
1832			r = int(o.param)
1833		}
1834		o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
1835		if p.As != AMOVW {
1836			o2 |= 1 << 22
1837		}
1838
1839	case 31: /* mov/movbu L(R),R -> lr[b] */
1840		o1 = c.omvl(p, &p.From, REGTMP)
1841
1842		if o1 == 0 {
1843			break
1844		}
1845		r := int(p.From.Reg)
1846		if r == 0 {
1847			r = int(o.param)
1848		}
1849		o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
1850		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
1851			o2 |= 1 << 22
1852		}
1853
1854	case 34: /* mov $lacon,R */
1855		o1 = c.omvl(p, &p.From, REGTMP)
1856
1857		if o1 == 0 {
1858			break
1859		}
1860
1861		o2 = c.oprrr(p, AADD, int(p.Scond))
1862		o2 |= REGTMP & 15
1863		r := int(p.From.Reg)
1864		if r == 0 {
1865			r = int(o.param)
1866		}
1867		o2 |= (uint32(r) & 15) << 16
1868		if p.To.Type != obj.TYPE_NONE {
1869			o2 |= (uint32(p.To.Reg) & 15) << 12
1870		}
1871
1872	case 35: /* mov PSR,R */
1873		o1 = 2<<23 | 0xf<<16 | 0<<0
1874
1875		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1876		o1 |= (uint32(p.From.Reg) & 1) << 22
1877		o1 |= (uint32(p.To.Reg) & 15) << 12
1878
1879	case 36: /* mov R,PSR */
1880		o1 = 2<<23 | 0x2cf<<12 | 0<<4
1881
1882		if p.Scond&C_FBIT != 0 {
1883			o1 ^= 0x010 << 12
1884		}
1885		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1886		o1 |= (uint32(p.To.Reg) & 1) << 22
1887		o1 |= (uint32(p.From.Reg) & 15) << 0
1888
1889	case 37: /* mov $con,PSR */
1890		c.aclass(&p.From)
1891
1892		o1 = 2<<23 | 0x2cf<<12 | 0<<4
1893		if p.Scond&C_FBIT != 0 {
1894			o1 ^= 0x010 << 12
1895		}
1896		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1897		o1 |= uint32(immrot(uint32(c.instoffset)))
1898		o1 |= (uint32(p.To.Reg) & 1) << 22
1899		o1 |= (uint32(p.From.Reg) & 15) << 0
1900
1901	case 38, 39:
1902		switch o.type_ {
1903		case 38: /* movm $con,oreg -> stm */
1904			o1 = 0x4 << 25
1905
1906			o1 |= uint32(p.From.Offset & 0xffff)
1907			o1 |= (uint32(p.To.Reg) & 15) << 16
1908			c.aclass(&p.To)
1909
1910		case 39: /* movm oreg,$con -> ldm */
1911			o1 = 0x4<<25 | 1<<20
1912
1913			o1 |= uint32(p.To.Offset & 0xffff)
1914			o1 |= (uint32(p.From.Reg) & 15) << 16
1915			c.aclass(&p.From)
1916		}
1917
1918		if c.instoffset != 0 {
1919			c.ctxt.Diag("offset must be zero in MOVM; %v", p)
1920		}
1921		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1922		if p.Scond&C_PBIT != 0 {
1923			o1 |= 1 << 24
1924		}
1925		if p.Scond&C_UBIT != 0 {
1926			o1 |= 1 << 23
1927		}
1928		if p.Scond&C_WBIT != 0 {
1929			o1 |= 1 << 21
1930		}
1931
1932	case 40: /* swp oreg,reg,reg */
1933		c.aclass(&p.From)
1934
1935		if c.instoffset != 0 {
1936			c.ctxt.Diag("offset must be zero in SWP")
1937		}
1938		o1 = 0x2<<23 | 0x9<<4
1939		if p.As != ASWPW {
1940			o1 |= 1 << 22
1941		}
1942		o1 |= (uint32(p.From.Reg) & 15) << 16
1943		o1 |= (uint32(p.Reg) & 15) << 0
1944		o1 |= (uint32(p.To.Reg) & 15) << 12
1945		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1946
1947	case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
1948		o1 = 0xe8fd8000
1949
1950	case 50: /* floating point store */
1951		v := c.regoff(&p.To)
1952
1953		r := int(p.To.Reg)
1954		if r == 0 {
1955			r = int(o.param)
1956		}
1957		o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
1958
1959	case 51: /* floating point load */
1960		v := c.regoff(&p.From)
1961
1962		r := int(p.From.Reg)
1963		if r == 0 {
1964			r = int(o.param)
1965		}
1966		o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
1967
1968	case 52: /* floating point store, int32 offset UGLY */
1969		o1 = c.omvl(p, &p.To, REGTMP)
1970
1971		if o1 == 0 {
1972			break
1973		}
1974		r := int(p.To.Reg)
1975		if r == 0 {
1976			r = int(o.param)
1977		}
1978		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
1979		o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
1980
1981	case 53: /* floating point load, int32 offset UGLY */
1982		o1 = c.omvl(p, &p.From, REGTMP)
1983
1984		if o1 == 0 {
1985			break
1986		}
1987		r := int(p.From.Reg)
1988		if r == 0 {
1989			r = int(o.param)
1990		}
1991		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
1992		o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
1993
1994	case 54: /* floating point arith */
1995		o1 = c.oprrr(p, p.As, int(p.Scond))
1996
1997		rf := int(p.From.Reg)
1998		rt := int(p.To.Reg)
1999		r := int(p.Reg)
2000		if r == 0 {
2001			switch p.As {
2002			case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
2003				AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
2004				c.ctxt.Diag("illegal combination: %v", p)
2005			default:
2006				r = rt
2007			}
2008		}
2009
2010		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2011
2012	case 55: /* negf freg, freg */
2013		o1 = c.oprrr(p, p.As, int(p.Scond))
2014
2015		rf := int(p.From.Reg)
2016		rt := int(p.To.Reg)
2017
2018		o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
2019
2020	case 56: /* move to FP[CS]R */
2021		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
2022
2023		o1 |= (uint32(p.From.Reg) & 15) << 12
2024
2025	case 57: /* move from FP[CS]R */
2026		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
2027
2028		o1 |= (uint32(p.To.Reg) & 15) << 12
2029
2030	case 58: /* movbu R,R */
2031		o1 = c.oprrr(p, AAND, int(p.Scond))
2032
2033		o1 |= uint32(immrot(0xff))
2034		rt := int(p.To.Reg)
2035		r := int(p.From.Reg)
2036		if p.To.Type == obj.TYPE_NONE {
2037			rt = 0
2038		}
2039		if r == 0 {
2040			r = rt
2041		}
2042		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2043
2044	case 59: /* movw/bu R<<I(R),R -> ldr indexed */
2045		if p.From.Reg == 0 {
2046			c.ctxt.Diag("source operand is not a memory address: %v", p)
2047			break
2048		}
2049		if p.From.Offset&(1<<4) != 0 {
2050			c.ctxt.Diag("bad shift in LDR")
2051			break
2052		}
2053		o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2054		if p.As == AMOVBU {
2055			o1 |= 1 << 22
2056		}
2057
2058	case 60: /* movb R(R),R -> ldrsb indexed */
2059		if p.From.Reg == 0 {
2060			c.ctxt.Diag("source operand is not a memory address: %v", p)
2061			break
2062		}
2063		if p.From.Offset&(^0xf) != 0 {
2064			c.ctxt.Diag("bad shift: %v", p)
2065			break
2066		}
2067		o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2068		switch p.As {
2069		case AMOVB, AMOVBS:
2070			o1 ^= 1<<5 | 1<<6
2071		case AMOVH, AMOVHS:
2072			o1 ^= 1 << 6
2073		default:
2074		}
2075		if p.Scond&C_UBIT != 0 {
2076			o1 &^= 1 << 23
2077		}
2078
2079	case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
2080		if p.To.Reg == 0 {
2081			c.ctxt.Diag("MOV to shifter operand")
2082		}
2083		o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
2084		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
2085			o1 |= 1 << 22
2086		}
2087
2088	case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */
2089		if p.To.Reg == 0 {
2090			c.ctxt.Diag("MOV to shifter operand")
2091		}
2092		if p.To.Offset&(^0xf) != 0 {
2093			c.ctxt.Diag("bad shift: %v", p)
2094		}
2095		o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
2096		o1 ^= 1 << 20
2097		if p.Scond&C_UBIT != 0 {
2098			o1 &^= 1 << 23
2099		}
2100
2101		/* reloc ops */
2102	case 64: /* mov/movb/movbu R,addr */
2103		o1 = c.omvl(p, &p.To, REGTMP)
2104
2105		if o1 == 0 {
2106			break
2107		}
2108		o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
2109		if o.flag&LPCREL != 0 {
2110			o3 = o2
2111			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2112		}
2113
2114	case 65: /* mov/movbu addr,R */
2115		o1 = c.omvl(p, &p.From, REGTMP)
2116
2117		if o1 == 0 {
2118			break
2119		}
2120		o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2121		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
2122			o2 |= 1 << 22
2123		}
2124		if o.flag&LPCREL != 0 {
2125			o3 = o2
2126			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2127		}
2128
2129	case 101: /* movw tlsvar,R, local exec*/
2130		o1 = c.omvl(p, &p.From, int(p.To.Reg))
2131
2132	case 102: /* movw tlsvar,R, initial exec*/
2133		o1 = c.omvl(p, &p.From, int(p.To.Reg))
2134		o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
2135
2136	case 103: /* word tlsvar, local exec */
2137		if p.To.Sym == nil {
2138			c.ctxt.Diag("nil sym in tls %v", p)
2139		}
2140		if p.To.Offset != 0 {
2141			c.ctxt.Diag("offset against tls var in %v", p)
2142		}
2143		// This case happens with words generated in the PC stream as part of
2144		// the literal c.pool.
2145		rel := obj.Addrel(c.cursym)
2146
2147		rel.Off = int32(c.pc)
2148		rel.Siz = 4
2149		rel.Sym = p.To.Sym
2150		rel.Type = objabi.R_TLS_LE
2151		o1 = 0
2152
2153	case 104: /* word tlsvar, initial exec */
2154		if p.To.Sym == nil {
2155			c.ctxt.Diag("nil sym in tls %v", p)
2156		}
2157		if p.To.Offset != 0 {
2158			c.ctxt.Diag("offset against tls var in %v", p)
2159		}
2160		rel := obj.Addrel(c.cursym)
2161		rel.Off = int32(c.pc)
2162		rel.Siz = 4
2163		rel.Sym = p.To.Sym
2164		rel.Type = objabi.R_TLS_IE
2165		rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
2166
2167	case 68: /* floating point store -> ADDR */
2168		o1 = c.omvl(p, &p.To, REGTMP)
2169
2170		if o1 == 0 {
2171			break
2172		}
2173		o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
2174		if o.flag&LPCREL != 0 {
2175			o3 = o2
2176			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2177		}
2178
2179	case 69: /* floating point load <- ADDR */
2180		o1 = c.omvl(p, &p.From, REGTMP)
2181
2182		if o1 == 0 {
2183			break
2184		}
2185		o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
2186		if o.flag&LPCREL != 0 {
2187			o3 = o2
2188			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2189		}
2190
2191		/* ArmV4 ops: */
2192	case 70: /* movh/movhu R,O(R) -> strh */
2193		c.aclass(&p.To)
2194
2195		r := int(p.To.Reg)
2196		if r == 0 {
2197			r = int(o.param)
2198		}
2199		o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
2200
2201	case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
2202		c.aclass(&p.From)
2203
2204		r := int(p.From.Reg)
2205		if r == 0 {
2206			r = int(o.param)
2207		}
2208		o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
2209		if p.As == AMOVB || p.As == AMOVBS {
2210			o1 ^= 1<<5 | 1<<6
2211		} else if p.As == AMOVH || p.As == AMOVHS {
2212			o1 ^= (1 << 6)
2213		}
2214
2215	case 72: /* movh/movhu R,L(R) -> strh */
2216		o1 = c.omvl(p, &p.To, REGTMP)
2217
2218		if o1 == 0 {
2219			break
2220		}
2221		r := int(p.To.Reg)
2222		if r == 0 {
2223			r = int(o.param)
2224		}
2225		o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
2226
2227	case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
2228		o1 = c.omvl(p, &p.From, REGTMP)
2229
2230		if o1 == 0 {
2231			break
2232		}
2233		r := int(p.From.Reg)
2234		if r == 0 {
2235			r = int(o.param)
2236		}
2237		o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
2238		if p.As == AMOVB || p.As == AMOVBS {
2239			o2 ^= 1<<5 | 1<<6
2240		} else if p.As == AMOVH || p.As == AMOVHS {
2241			o2 ^= (1 << 6)
2242		}
2243
2244	case 74: /* bx $I */
2245		c.ctxt.Diag("ABX $I")
2246
2247	case 75: /* bx O(R) */
2248		c.aclass(&p.To)
2249
2250		if c.instoffset != 0 {
2251			c.ctxt.Diag("non-zero offset in ABX")
2252		}
2253
2254		/*
2255			o1 = 	c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12);	// mov PC, LR
2256			o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0);		// BX R
2257		*/
2258		// p->to.reg may be REGLINK
2259		o1 = c.oprrr(p, AADD, int(p.Scond))
2260
2261		o1 |= uint32(immrot(uint32(c.instoffset)))
2262		o1 |= (uint32(p.To.Reg) & 15) << 16
2263		o1 |= (REGTMP & 15) << 12
2264		o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
2265		o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15            // BX Rtmp
2266
2267	case 76: /* bx O(R) when returning from fn*/
2268		c.ctxt.Diag("ABXRET")
2269
2270	case 77: /* ldrex oreg,reg */
2271		c.aclass(&p.From)
2272
2273		if c.instoffset != 0 {
2274			c.ctxt.Diag("offset must be zero in LDREX")
2275		}
2276		o1 = 0x19<<20 | 0xf9f
2277		o1 |= (uint32(p.From.Reg) & 15) << 16
2278		o1 |= (uint32(p.To.Reg) & 15) << 12
2279		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2280
2281	case 78: /* strex reg,oreg,reg */
2282		c.aclass(&p.From)
2283
2284		if c.instoffset != 0 {
2285			c.ctxt.Diag("offset must be zero in STREX")
2286		}
2287		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
2288			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2289		}
2290		o1 = 0x18<<20 | 0xf90
2291		o1 |= (uint32(p.From.Reg) & 15) << 16
2292		o1 |= (uint32(p.Reg) & 15) << 0
2293		o1 |= (uint32(p.To.Reg) & 15) << 12
2294		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2295
2296	case 80: /* fmov zfcon,freg */
2297		if p.As == AMOVD {
2298			o1 = 0xeeb00b00 // VMOV imm 64
2299			o2 = c.oprrr(p, ASUBD, int(p.Scond))
2300		} else {
2301			o1 = 0x0eb00a00 // VMOV imm 32
2302			o2 = c.oprrr(p, ASUBF, int(p.Scond))
2303		}
2304
2305		v := int32(0x70) // 1.0
2306		r := (int(p.To.Reg) & 15) << 0
2307
2308		// movf $1.0, r
2309		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2310
2311		o1 |= (uint32(r) & 15) << 12
2312		o1 |= (uint32(v) & 0xf) << 0
2313		o1 |= (uint32(v) & 0xf0) << 12
2314
2315		// subf r,r,r
2316		o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
2317
2318	case 81: /* fmov sfcon,freg */
2319		o1 = 0x0eb00a00 // VMOV imm 32
2320		if p.As == AMOVD {
2321			o1 = 0xeeb00b00 // VMOV imm 64
2322		}
2323		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2324		o1 |= (uint32(p.To.Reg) & 15) << 12
2325		v := int32(c.chipfloat5(p.From.Val.(float64)))
2326		o1 |= (uint32(v) & 0xf) << 0
2327		o1 |= (uint32(v) & 0xf0) << 12
2328
2329	case 82: /* fcmp freg,freg, */
2330		o1 = c.oprrr(p, p.As, int(p.Scond))
2331
2332		o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
2333		o2 = 0x0ef1fa10 // VMRS R15
2334		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2335
2336	case 83: /* fcmp freg,, */
2337		o1 = c.oprrr(p, p.As, int(p.Scond))
2338
2339		o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
2340		o2 = 0x0ef1fa10 // VMRS R15
2341		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2342
2343	case 84: /* movfw freg,freg - truncate float-to-fix */
2344		o1 = c.oprrr(p, p.As, int(p.Scond))
2345
2346		o1 |= (uint32(p.From.Reg) & 15) << 0
2347		o1 |= (uint32(p.To.Reg) & 15) << 12
2348
2349	case 85: /* movwf freg,freg - fix-to-float */
2350		o1 = c.oprrr(p, p.As, int(p.Scond))
2351
2352		o1 |= (uint32(p.From.Reg) & 15) << 0
2353		o1 |= (uint32(p.To.Reg) & 15) << 12
2354
2355		// macro for movfw freg,FTMP; movw FTMP,reg
2356	case 86: /* movfw freg,reg - truncate float-to-fix */
2357		o1 = c.oprrr(p, p.As, int(p.Scond))
2358
2359		o1 |= (uint32(p.From.Reg) & 15) << 0
2360		o1 |= (FREGTMP & 15) << 12
2361		o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
2362		o2 |= (FREGTMP & 15) << 16
2363		o2 |= (uint32(p.To.Reg) & 15) << 12
2364
2365		// macro for movw reg,FTMP; movwf FTMP,freg
2366	case 87: /* movwf reg,freg - fix-to-float */
2367		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2368
2369		o1 |= (uint32(p.From.Reg) & 15) << 12
2370		o1 |= (FREGTMP & 15) << 16
2371		o2 = c.oprrr(p, p.As, int(p.Scond))
2372		o2 |= (FREGTMP & 15) << 0
2373		o2 |= (uint32(p.To.Reg) & 15) << 12
2374
2375	case 88: /* movw reg,freg  */
2376		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2377
2378		o1 |= (uint32(p.From.Reg) & 15) << 12
2379		o1 |= (uint32(p.To.Reg) & 15) << 16
2380
2381	case 89: /* movw freg,reg  */
2382		o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
2383
2384		o1 |= (uint32(p.From.Reg) & 15) << 16
2385		o1 |= (uint32(p.To.Reg) & 15) << 12
2386
2387	case 91: /* ldrexd oreg,reg */
2388		c.aclass(&p.From)
2389
2390		if c.instoffset != 0 {
2391			c.ctxt.Diag("offset must be zero in LDREX")
2392		}
2393		o1 = 0x1b<<20 | 0xf9f
2394		o1 |= (uint32(p.From.Reg) & 15) << 16
2395		o1 |= (uint32(p.To.Reg) & 15) << 12
2396		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2397
2398	case 92: /* strexd reg,oreg,reg */
2399		c.aclass(&p.From)
2400
2401		if c.instoffset != 0 {
2402			c.ctxt.Diag("offset must be zero in STREX")
2403		}
2404		if p.Reg&1 != 0 {
2405			c.ctxt.Diag("source register must be even in STREXD: %v", p)
2406		}
2407		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
2408			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2409		}
2410		o1 = 0x1a<<20 | 0xf90
2411		o1 |= (uint32(p.From.Reg) & 15) << 16
2412		o1 |= (uint32(p.Reg) & 15) << 0
2413		o1 |= (uint32(p.To.Reg) & 15) << 12
2414		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2415
2416	case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
2417		o1 = c.omvl(p, &p.From, REGTMP)
2418
2419		if o1 == 0 {
2420			break
2421		}
2422		o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2423		if p.As == AMOVB || p.As == AMOVBS {
2424			o2 ^= 1<<5 | 1<<6
2425		} else if p.As == AMOVH || p.As == AMOVHS {
2426			o2 ^= (1 << 6)
2427		}
2428		if o.flag&LPCREL != 0 {
2429			o3 = o2
2430			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2431		}
2432
2433	case 94: /* movh/movhu R,addr -> strh */
2434		o1 = c.omvl(p, &p.To, REGTMP)
2435
2436		if o1 == 0 {
2437			break
2438		}
2439		o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
2440		if o.flag&LPCREL != 0 {
2441			o3 = o2
2442			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2443		}
2444
2445	case 95: /* PLD off(reg) */
2446		o1 = 0xf5d0f000
2447
2448		o1 |= (uint32(p.From.Reg) & 15) << 16
2449		if p.From.Offset < 0 {
2450			o1 &^= (1 << 23)
2451			o1 |= uint32((-p.From.Offset) & 0xfff)
2452		} else {
2453			o1 |= uint32(p.From.Offset & 0xfff)
2454		}
2455
2456	// This is supposed to be something that stops execution.
2457	// It's not supposed to be reached, ever, but if it is, we'd
2458	// like to be able to tell how we got there. Assemble as
2459	// 0xf7fabcfd which is guaranteed to raise undefined instruction
2460	// exception.
2461	case 96: /* UNDEF */
2462		o1 = 0xf7fabcfd
2463
2464	case 97: /* CLZ Rm, Rd */
2465		o1 = c.oprrr(p, p.As, int(p.Scond))
2466
2467		o1 |= (uint32(p.To.Reg) & 15) << 12
2468		o1 |= (uint32(p.From.Reg) & 15) << 0
2469
2470	case 98: /* MULW{T,B} Rs, Rm, Rd */
2471		o1 = c.oprrr(p, p.As, int(p.Scond))
2472
2473		o1 |= (uint32(p.To.Reg) & 15) << 16
2474		o1 |= (uint32(p.From.Reg) & 15) << 8
2475		o1 |= (uint32(p.Reg) & 15) << 0
2476
2477	case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
2478		o1 = c.oprrr(p, p.As, int(p.Scond))
2479
2480		o1 |= (uint32(p.To.Reg) & 15) << 16
2481		o1 |= (uint32(p.From.Reg) & 15) << 8
2482		o1 |= (uint32(p.Reg) & 15) << 0
2483		o1 |= uint32((p.To.Offset & 15) << 12)
2484
2485	case 105: /* divhw r,[r,]r */
2486		o1 = c.oprrr(p, p.As, int(p.Scond))
2487		rf := int(p.From.Reg)
2488		rt := int(p.To.Reg)
2489		r := int(p.Reg)
2490		if r == 0 {
2491			r = rt
2492		}
2493		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
2494
2495	case 110: /* dmb [mbop | $con] */
2496		o1 = 0xf57ff050
2497		mbop := uint32(0)
2498
2499		switch c.aclass(&p.From) {
2500		case C_SPR:
2501			for _, f := range mbOp {
2502				if f.reg == p.From.Reg {
2503					mbop = f.enc
2504					break
2505				}
2506			}
2507		case C_RCON:
2508			for _, f := range mbOp {
2509				enc := uint32(c.instoffset)
2510				if f.enc == enc {
2511					mbop = enc
2512					break
2513				}
2514			}
2515		case C_NONE:
2516			mbop = 0xf
2517		}
2518
2519		if mbop == 0 {
2520			c.ctxt.Diag("illegal mb option:\n%v", p)
2521		}
2522		o1 |= mbop
2523	}
2524
2525	out[0] = o1
2526	out[1] = o2
2527	out[2] = o3
2528	out[3] = o4
2529	out[4] = o5
2530	out[5] = o6
2531}
2532
2533func (c *ctxt5) movxt(p *obj.Prog) uint32 {
2534	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2535	switch p.As {
2536	case AMOVB, AMOVBS:
2537		o1 |= 0x6af<<16 | 0x7<<4
2538	case AMOVH, AMOVHS:
2539		o1 |= 0x6bf<<16 | 0x7<<4
2540	case AMOVBU:
2541		o1 |= 0x6ef<<16 | 0x7<<4
2542	case AMOVHU:
2543		o1 |= 0x6ff<<16 | 0x7<<4
2544	default:
2545		c.ctxt.Diag("illegal combination: %v", p)
2546	}
2547	switch p.From.Offset &^ 0xf {
2548	// only 0/8/16/24 bits rotation is accepted
2549	case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
2550		o1 |= uint32(p.From.Offset) & 0xc0f
2551	default:
2552		c.ctxt.Diag("illegal shift: %v", p)
2553	}
2554	o1 |= (uint32(p.To.Reg) & 15) << 12
2555	return o1
2556}
2557
2558func (c *ctxt5) mov(p *obj.Prog) uint32 {
2559	c.aclass(&p.From)
2560	o1 := c.oprrr(p, p.As, int(p.Scond))
2561	o1 |= uint32(p.From.Offset)
2562	rt := int(p.To.Reg)
2563	if p.To.Type == obj.TYPE_NONE {
2564		rt = 0
2565	}
2566	r := int(p.Reg)
2567	if p.As == AMOVW || p.As == AMVN {
2568		r = 0
2569	} else if r == 0 {
2570		r = rt
2571	}
2572	o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2573	return o1
2574}
2575
2576func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
2577	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2578	if sc&C_SBIT != 0 {
2579		o |= 1 << 20
2580	}
2581	switch a {
2582	case ADIVHW:
2583		return o | 0x71<<20 | 0xf<<12 | 0x1<<4
2584	case ADIVUHW:
2585		return o | 0x73<<20 | 0xf<<12 | 0x1<<4
2586	case AMMUL:
2587		return o | 0x75<<20 | 0xf<<12 | 0x1<<4
2588	case AMULS:
2589		return o | 0x6<<20 | 0x9<<4
2590	case AMMULA:
2591		return o | 0x75<<20 | 0x1<<4
2592	case AMMULS:
2593		return o | 0x75<<20 | 0xd<<4
2594	case AMULU, AMUL:
2595		return o | 0x0<<21 | 0x9<<4
2596	case AMULA:
2597		return o | 0x1<<21 | 0x9<<4
2598	case AMULLU:
2599		return o | 0x4<<21 | 0x9<<4
2600	case AMULL:
2601		return o | 0x6<<21 | 0x9<<4
2602	case AMULALU:
2603		return o | 0x5<<21 | 0x9<<4
2604	case AMULAL:
2605		return o | 0x7<<21 | 0x9<<4
2606	case AAND:
2607		return o | 0x0<<21
2608	case AEOR:
2609		return o | 0x1<<21
2610	case ASUB:
2611		return o | 0x2<<21
2612	case ARSB:
2613		return o | 0x3<<21
2614	case AADD:
2615		return o | 0x4<<21
2616	case AADC:
2617		return o | 0x5<<21
2618	case ASBC:
2619		return o | 0x6<<21
2620	case ARSC:
2621		return o | 0x7<<21
2622	case ATST:
2623		return o | 0x8<<21 | 1<<20
2624	case ATEQ:
2625		return o | 0x9<<21 | 1<<20
2626	case ACMP:
2627		return o | 0xa<<21 | 1<<20
2628	case ACMN:
2629		return o | 0xb<<21 | 1<<20
2630	case AORR:
2631		return o | 0xc<<21
2632
2633	case AMOVB, AMOVH, AMOVW:
2634		if sc&(C_PBIT|C_WBIT) != 0 {
2635			c.ctxt.Diag("invalid .P/.W suffix: %v", p)
2636		}
2637		return o | 0xd<<21
2638	case ABIC:
2639		return o | 0xe<<21
2640	case AMVN:
2641		return o | 0xf<<21
2642	case ASLL:
2643		return o | 0xd<<21 | 0<<5
2644	case ASRL:
2645		return o | 0xd<<21 | 1<<5
2646	case ASRA:
2647		return o | 0xd<<21 | 2<<5
2648	case ASWI:
2649		return o | 0xf<<24
2650
2651	case AADDD:
2652		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
2653	case AADDF:
2654		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
2655	case ASUBD:
2656		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
2657	case ASUBF:
2658		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
2659	case AMULD:
2660		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
2661	case AMULF:
2662		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
2663	case ANMULD:
2664		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
2665	case ANMULF:
2666		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
2667	case AMULAD:
2668		return o | 0xe<<24 | 0xb<<8
2669	case AMULAF:
2670		return o | 0xe<<24 | 0xa<<8
2671	case AMULSD:
2672		return o | 0xe<<24 | 0xb<<8 | 0x4<<4
2673	case AMULSF:
2674		return o | 0xe<<24 | 0xa<<8 | 0x4<<4
2675	case ANMULAD:
2676		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
2677	case ANMULAF:
2678		return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
2679	case ANMULSD:
2680		return o | 0xe<<24 | 0x1<<20 | 0xb<<8
2681	case ANMULSF:
2682		return o | 0xe<<24 | 0x1<<20 | 0xa<<8
2683	case AFMULAD:
2684		return o | 0xe<<24 | 0xa<<20 | 0xb<<8
2685	case AFMULAF:
2686		return o | 0xe<<24 | 0xa<<20 | 0xa<<8
2687	case AFMULSD:
2688		return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
2689	case AFMULSF:
2690		return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
2691	case AFNMULAD:
2692		return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
2693	case AFNMULAF:
2694		return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
2695	case AFNMULSD:
2696		return o | 0xe<<24 | 0x9<<20 | 0xb<<8
2697	case AFNMULSF:
2698		return o | 0xe<<24 | 0x9<<20 | 0xa<<8
2699	case ADIVD:
2700		return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
2701	case ADIVF:
2702		return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
2703	case ASQRTD:
2704		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
2705	case ASQRTF:
2706		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
2707	case AABSD:
2708		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
2709	case AABSF:
2710		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
2711	case ANEGD:
2712		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
2713	case ANEGF:
2714		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
2715	case ACMPD:
2716		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
2717	case ACMPF:
2718		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
2719
2720	case AMOVF:
2721		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
2722	case AMOVD:
2723		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
2724
2725	case AMOVDF:
2726		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
2727	case AMOVFD:
2728		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
2729
2730	case AMOVWF:
2731		if sc&C_UBIT == 0 {
2732			o |= 1 << 7 /* signed */
2733		}
2734		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
2735
2736	case AMOVWD:
2737		if sc&C_UBIT == 0 {
2738			o |= 1 << 7 /* signed */
2739		}
2740		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
2741
2742	case AMOVFW:
2743		if sc&C_UBIT == 0 {
2744			o |= 1 << 16 /* signed */
2745		}
2746		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
2747
2748	case AMOVDW:
2749		if sc&C_UBIT == 0 {
2750			o |= 1 << 16 /* signed */
2751		}
2752		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
2753
2754	case -AMOVWF: // copy WtoF
2755		return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
2756
2757	case -AMOVFW: // copy FtoW
2758		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
2759
2760	case -ACMP: // cmp imm
2761		return o | 0x3<<24 | 0x5<<20
2762
2763	case ABFX:
2764		return o | 0x3d<<21 | 0x5<<4
2765
2766	case ABFXU:
2767		return o | 0x3f<<21 | 0x5<<4
2768
2769	case ABFC:
2770		return o | 0x3e<<21 | 0x1f
2771
2772	case ABFI:
2773		return o | 0x3e<<21 | 0x1<<4
2774
2775	case AXTAB:
2776		return o | 0x6a<<20 | 0x7<<4
2777
2778	case AXTAH:
2779		return o | 0x6b<<20 | 0x7<<4
2780
2781	case AXTABU:
2782		return o | 0x6e<<20 | 0x7<<4
2783
2784	case AXTAHU:
2785		return o | 0x6f<<20 | 0x7<<4
2786
2787		// CLZ doesn't support .nil
2788	case ACLZ:
2789		return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
2790
2791	case AREV:
2792		return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
2793
2794	case AREV16:
2795		return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
2796
2797	case AREVSH:
2798		return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
2799
2800	case ARBIT:
2801		return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
2802
2803	case AMULWT:
2804		return o&(0xf<<28) | 0x12<<20 | 0xe<<4
2805
2806	case AMULWB:
2807		return o&(0xf<<28) | 0x12<<20 | 0xa<<4
2808
2809	case AMULBB:
2810		return o&(0xf<<28) | 0x16<<20 | 0x8<<4
2811
2812	case AMULAWT:
2813		return o&(0xf<<28) | 0x12<<20 | 0xc<<4
2814
2815	case AMULAWB:
2816		return o&(0xf<<28) | 0x12<<20 | 0x8<<4
2817
2818	case AMULABB:
2819		return o&(0xf<<28) | 0x10<<20 | 0x8<<4
2820
2821	case ABL: // BLX REG
2822		return o&(0xf<<28) | 0x12fff3<<4
2823	}
2824
2825	c.ctxt.Diag("%v: bad rrr %d", p, a)
2826	return 0
2827}
2828
2829func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
2830	sc &= C_SCOND
2831	sc ^= C_SCOND_XOR
2832	if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
2833		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
2834	}
2835	if sc != 0xe {
2836		c.ctxt.Diag("%v: .COND on bcond instruction", p)
2837	}
2838	switch a {
2839	case ABEQ:
2840		return 0x0<<28 | 0x5<<25
2841	case ABNE:
2842		return 0x1<<28 | 0x5<<25
2843	case ABCS:
2844		return 0x2<<28 | 0x5<<25
2845	case ABHS:
2846		return 0x2<<28 | 0x5<<25
2847	case ABCC:
2848		return 0x3<<28 | 0x5<<25
2849	case ABLO:
2850		return 0x3<<28 | 0x5<<25
2851	case ABMI:
2852		return 0x4<<28 | 0x5<<25
2853	case ABPL:
2854		return 0x5<<28 | 0x5<<25
2855	case ABVS:
2856		return 0x6<<28 | 0x5<<25
2857	case ABVC:
2858		return 0x7<<28 | 0x5<<25
2859	case ABHI:
2860		return 0x8<<28 | 0x5<<25
2861	case ABLS:
2862		return 0x9<<28 | 0x5<<25
2863	case ABGE:
2864		return 0xa<<28 | 0x5<<25
2865	case ABLT:
2866		return 0xb<<28 | 0x5<<25
2867	case ABGT:
2868		return 0xc<<28 | 0x5<<25
2869	case ABLE:
2870		return 0xd<<28 | 0x5<<25
2871	case AB:
2872		return 0xe<<28 | 0x5<<25
2873	}
2874
2875	c.ctxt.Diag("%v: bad bra %v", p, a)
2876	return 0
2877}
2878
2879func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
2880	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2881	if sc&C_PBIT == 0 {
2882		o |= 1 << 24
2883	}
2884	if sc&C_UBIT == 0 {
2885		o |= 1 << 23
2886	}
2887	if sc&C_WBIT != 0 {
2888		o |= 1 << 21
2889	}
2890	o |= 1<<26 | 1<<20
2891	if v < 0 {
2892		if sc&C_UBIT != 0 {
2893			c.ctxt.Diag(".U on neg offset")
2894		}
2895		v = -v
2896		o ^= 1 << 23
2897	}
2898
2899	if v >= 1<<12 || v < 0 {
2900		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2901	}
2902	o |= uint32(v)
2903	o |= (uint32(b) & 15) << 16
2904	o |= (uint32(r) & 15) << 12
2905	return o
2906}
2907
2908func (c *ctxt5) olhr(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_WBIT != 0 {
2914		o |= 1 << 21
2915	}
2916	o |= 1<<23 | 1<<20 | 0xb<<4
2917	if v < 0 {
2918		v = -v
2919		o ^= 1 << 23
2920	}
2921
2922	if v >= 1<<8 || v < 0 {
2923		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2924	}
2925	o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
2926	o |= (uint32(b) & 15) << 16
2927	o |= (uint32(r) & 15) << 12
2928	return o
2929}
2930
2931func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
2932	o := c.olr(v, b, r, sc) ^ (1 << 20)
2933	if a != AMOVW {
2934		o |= 1 << 22
2935	}
2936	return o
2937}
2938
2939func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
2940	o := c.olhr(v, b, r, sc) ^ (1 << 20)
2941	return o
2942}
2943
2944func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
2945	return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
2946}
2947
2948func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
2949	return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
2950}
2951
2952func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
2953	return c.olr(int32(i), b, r, sc) ^ (1 << 25)
2954}
2955
2956func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
2957	return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
2958}
2959
2960func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
2961	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2962	if sc&C_PBIT == 0 {
2963		o |= 1 << 24
2964	}
2965	if sc&C_WBIT != 0 {
2966		o |= 1 << 21
2967	}
2968	o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
2969	if v < 0 {
2970		v = -v
2971		o ^= 1 << 23
2972	}
2973
2974	if v&3 != 0 {
2975		c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
2976	} else if v >= 1<<10 || v < 0 {
2977		c.ctxt.Diag("literal span too large: %d\n%v", v, p)
2978	}
2979	o |= (uint32(v) >> 2) & 0xFF
2980	o |= (uint32(b) & 15) << 16
2981	o |= (uint32(r) & 15) << 12
2982
2983	switch a {
2984	default:
2985		c.ctxt.Diag("bad fst %v", a)
2986		fallthrough
2987
2988	case AMOVD:
2989		o |= 1 << 8
2990		fallthrough
2991
2992	case AMOVF:
2993		break
2994	}
2995
2996	return o
2997}
2998
2999// MOVW $"lower 16-bit", Reg
3000func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3001	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
3002	o1 |= 0x30 << 20
3003	o1 |= (uint32(dr) & 15) << 12
3004	o1 |= uint32(a.Offset) & 0x0fff
3005	o1 |= (uint32(a.Offset) & 0xf000) << 4
3006	return o1
3007}
3008
3009// MVN $C_NCON, Reg -> MOVW $C_RCON, Reg
3010func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3011	o1 := c.oprrr(p, AMOVW, int(p.Scond))
3012	o1 |= (uint32(dr) & 15) << 12
3013	v := immrot(^uint32(a.Offset))
3014	if v == 0 {
3015		c.ctxt.Diag("%v: missing literal", p)
3016		return 0
3017	}
3018	o1 |= uint32(v)
3019	return o1
3020}
3021
3022func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3023	var o1 uint32
3024	if p.Pool == nil {
3025		c.aclass(a)
3026		v := immrot(^uint32(c.instoffset))
3027		if v == 0 {
3028			c.ctxt.Diag("%v: missing literal", p)
3029			return 0
3030		}
3031
3032		o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
3033		o1 |= uint32(v)
3034		o1 |= (uint32(dr) & 15) << 12
3035	} else {
3036		v := int32(p.Pool.Pc - p.Pc - 8)
3037		o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
3038	}
3039
3040	return o1
3041}
3042
3043func (c *ctxt5) chipzero5(e float64) int {
3044	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
3045	if buildcfg.GOARM < 7 || math.Float64bits(e) != 0 {
3046		return -1
3047	}
3048	return 0
3049}
3050
3051func (c *ctxt5) chipfloat5(e float64) int {
3052	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
3053	if buildcfg.GOARM < 7 {
3054		return -1
3055	}
3056
3057	ei := math.Float64bits(e)
3058	l := uint32(ei)
3059	h := uint32(ei >> 32)
3060
3061	if l != 0 || h&0xffff != 0 {
3062		return -1
3063	}
3064	h1 := h & 0x7fc00000
3065	if h1 != 0x40000000 && h1 != 0x3fc00000 {
3066		return -1
3067	}
3068	n := 0
3069
3070	// sign bit (a)
3071	if h&0x80000000 != 0 {
3072		n |= 1 << 7
3073	}
3074
3075	// exp sign bit (b)
3076	if h1 == 0x3fc00000 {
3077		n |= 1 << 6
3078	}
3079
3080	// rest of exp and mantissa (cd-efgh)
3081	n |= int((h >> 16) & 0x3f)
3082
3083	//print("match %.8lux %.8lux %d\n", l, h, n);
3084	return n
3085}
3086
3087func nocache(p *obj.Prog) {
3088	p.Optab = 0
3089	p.From.Class = 0
3090	if p.GetFrom3() != nil {
3091		p.GetFrom3().Class = 0
3092	}
3093	p.To.Class = 0
3094}
3095