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