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