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