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