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