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