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 "github.com/twitchyliquid64/golang-asm/obj"
35 "github.com/twitchyliquid64/golang-asm/objabi"
36 "fmt"
37 "log"
38 "math"
39 "sort"
40 )
41
42
43
44
45 type ctxt5 struct {
46 ctxt *obj.Link
47 newprog obj.ProgAlloc
48 cursym *obj.LSym
49 printp *obj.Prog
50 blitrl *obj.Prog
51 elitrl *obj.Prog
52 autosize int64
53 instoffset int64
54 pc int64
55 pool struct {
56 start uint32
57 size uint32
58 extra uint32
59 }
60 }
61
62 type Optab struct {
63 as obj.As
64 a1 uint8
65 a2 int8
66 a3 uint8
67 type_ uint8
68 size int8
69 param int16
70 flag int8
71 pcrelsiz uint8
72 scond uint8
73 }
74
75 type Opcross [32][2][32]uint8
76
77 const (
78 LFROM = 1 << 0
79 LTO = 1 << 1
80 LPOOL = 1 << 2
81 LPCREL = 1 << 3
82 )
83
84 var optab = []Optab{
85
87 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0},
88 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
89 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
90 {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
91 {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
92 {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
93 {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
94 {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
95 {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
96 {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0},
97 {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
98 {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
99 {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
100 {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
101 {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
102 {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
103 {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
104 {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
105 {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0},
106 {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
107 {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
108 {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
109 {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
110 {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
111 {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
112 {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
113 {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0},
114 {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT},
115 {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0},
116 {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
117 {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0},
118 {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
119 {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
120 {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0},
121 {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
122 {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
123 {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0},
124 {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0},
125 {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT},
126 {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT},
127 {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT},
128 {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT},
129 {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0},
130 {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0},
131 {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0},
132 {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0},
133 {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0},
134 {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0},
135 {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0},
136 {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
137 {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
138 {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0},
139 {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0},
140 {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
141 {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
142 {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
143 {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
144 {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
145 {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
146 {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
147 {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
148 {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
149 {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
150 {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
151 {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
152 {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
153 {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
154 {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0},
155 {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
156 {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
157 {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
158 {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
159 {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
160 {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0},
161 {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0},
162 {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
163 {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
164 {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
165 {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
166 {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
167 {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
168 {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0},
169 {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0},
170 {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
171 {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
172 {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0},
173 {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
174 {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
175 {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
176 {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT},
177 {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT},
178 {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0},
179 {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0},
180 {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0},
181 {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0},
182 {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT},
183 {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0},
184 {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0},
185 {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
186 {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
187 {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
188 {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
189 {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
190 {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
191 {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
192 {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
193 {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
194 {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
195 {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
196 {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
197 {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0},
198 {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0},
199 {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT},
200 {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
201 {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
202 {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
203 {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
204 {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
205 {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
206 {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
207 {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
208 {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
209 {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
210 {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
211 {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
212 {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
213 {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
214 {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
215 {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
216 {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
217 {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
218 {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0},
219 {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0},
220 {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
221 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
222 {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
223 {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
224 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
225 {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
226 {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT},
227 {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0},
228 {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0},
229 {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0},
230 {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
231 {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
232 {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0},
233 {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0},
234 {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
235 {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
236 {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
237 {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
238 {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
239 {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
240 {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
241 {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
242 {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
243 {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
244 {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0},
245 {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0},
246 {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
247 {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
248 {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0},
249 {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0},
250 {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
251 {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
252 {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
253 {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
254 {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
255 {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
256 {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
257 {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
258 {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
259 {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
260 {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
261 {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
262 {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
263 {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
264 {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
265 {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
266 {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
267 {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
268 {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
269 {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
270 {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
271 {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
272 {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
273 {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
274 {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
275 {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
276 {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
277 {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
278 {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
279 {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
280 {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
281 {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
282 {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
283 {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
284 {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
285 {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
286 {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
287 {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
288 {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
289 {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
290 {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
291 {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
292 {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
293 {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
294 {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
295 {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
296 {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
297 {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
298 {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
299 {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
300 {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
301 {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
302 {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
303 {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
304 {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0},
305 {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0},
306 {ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
307 {ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
308 {ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
309 {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0},
310 {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0},
311 {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0},
312 {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0},
313 {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT},
314 {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT},
315 {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT},
316 {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT},
317 {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
318 {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
319 {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
320 {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
321 {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
322 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
323 {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
324 {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0},
325 {AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT},
326 {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0},
327 {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0},
328 {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0},
329 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
330 {obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
331 {obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
332 {obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
333 {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
334 {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
335 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0},
336 }
337
338 var mbOp = []struct {
339 reg int16
340 enc uint32
341 }{
342 {REG_MB_SY, 15},
343 {REG_MB_ST, 14},
344 {REG_MB_ISH, 11},
345 {REG_MB_ISHST, 10},
346 {REG_MB_NSH, 7},
347 {REG_MB_NSHST, 6},
348 {REG_MB_OSH, 3},
349 {REG_MB_OSHST, 2},
350 }
351
352 var oprange [ALAST & obj.AMask][]Optab
353
354 var xcmp [C_GOK + 1][C_GOK + 1]bool
355
356 var (
357 deferreturn *obj.LSym
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 && objabi.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 deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
1222
1223 symdiv = ctxt.Lookup("runtime._div")
1224 symdivu = ctxt.Lookup("runtime._divu")
1225 symmod = ctxt.Lookup("runtime._mod")
1226 symmodu = ctxt.Lookup("runtime._modu")
1227
1228 var n int
1229
1230 for i := 0; i < C_GOK; i++ {
1231 for n = 0; n < C_GOK; n++ {
1232 if cmp(n, i) {
1233 xcmp[i][n] = true
1234 }
1235 }
1236 }
1237 for n = 0; optab[n].as != obj.AXXX; n++ {
1238 if optab[n].flag&LPCREL != 0 {
1239 if ctxt.Flag_shared {
1240 optab[n].size += int8(optab[n].pcrelsiz)
1241 } else {
1242 optab[n].flag &^= LPCREL
1243 }
1244 }
1245 }
1246
1247 sort.Sort(ocmp(optab[:n]))
1248 for i := 0; i < n; i++ {
1249 r := optab[i].as
1250 r0 := r & obj.AMask
1251 start := i
1252 for optab[i].as == r {
1253 i++
1254 }
1255 oprange[r0] = optab[start:i]
1256 i--
1257
1258 switch r {
1259 default:
1260 ctxt.Diag("unknown op in build: %v", r)
1261 ctxt.DiagFlush()
1262 log.Fatalf("bad code")
1263
1264 case AADD:
1265 opset(ASUB, r0)
1266 opset(ARSB, r0)
1267 opset(AADC, r0)
1268 opset(ASBC, r0)
1269 opset(ARSC, r0)
1270
1271 case AORR:
1272 opset(AEOR, r0)
1273 opset(ABIC, r0)
1274
1275 case ACMP:
1276 opset(ATEQ, r0)
1277 opset(ACMN, r0)
1278 opset(ATST, r0)
1279
1280 case AMVN:
1281 break
1282
1283 case ABEQ:
1284 opset(ABNE, r0)
1285 opset(ABCS, r0)
1286 opset(ABHS, r0)
1287 opset(ABCC, r0)
1288 opset(ABLO, r0)
1289 opset(ABMI, r0)
1290 opset(ABPL, r0)
1291 opset(ABVS, r0)
1292 opset(ABVC, r0)
1293 opset(ABHI, r0)
1294 opset(ABLS, r0)
1295 opset(ABGE, r0)
1296 opset(ABLT, r0)
1297 opset(ABGT, r0)
1298 opset(ABLE, r0)
1299
1300 case ASLL:
1301 opset(ASRL, r0)
1302 opset(ASRA, r0)
1303
1304 case AMUL:
1305 opset(AMULU, r0)
1306
1307 case ADIV:
1308 opset(AMOD, r0)
1309 opset(AMODU, r0)
1310 opset(ADIVU, r0)
1311
1312 case ADIVHW:
1313 opset(ADIVUHW, r0)
1314
1315 case AMOVW,
1316 AMOVB,
1317 AMOVBS,
1318 AMOVBU,
1319 AMOVH,
1320 AMOVHS,
1321 AMOVHU:
1322 break
1323
1324 case ASWPW:
1325 opset(ASWPBU, r0)
1326
1327 case AB,
1328 ABL,
1329 ABX,
1330 ABXRET,
1331 obj.ADUFFZERO,
1332 obj.ADUFFCOPY,
1333 ASWI,
1334 AWORD,
1335 AMOVM,
1336 ARFE,
1337 obj.ATEXT:
1338 break
1339
1340 case AADDF:
1341 opset(AADDD, r0)
1342 opset(ASUBF, r0)
1343 opset(ASUBD, r0)
1344 opset(AMULF, r0)
1345 opset(AMULD, r0)
1346 opset(ANMULF, r0)
1347 opset(ANMULD, r0)
1348 opset(AMULAF, r0)
1349 opset(AMULAD, r0)
1350 opset(AMULSF, r0)
1351 opset(AMULSD, r0)
1352 opset(ANMULAF, r0)
1353 opset(ANMULAD, r0)
1354 opset(ANMULSF, r0)
1355 opset(ANMULSD, r0)
1356 opset(AFMULAF, r0)
1357 opset(AFMULAD, r0)
1358 opset(AFMULSF, r0)
1359 opset(AFMULSD, r0)
1360 opset(AFNMULAF, r0)
1361 opset(AFNMULAD, r0)
1362 opset(AFNMULSF, r0)
1363 opset(AFNMULSD, r0)
1364 opset(ADIVF, r0)
1365 opset(ADIVD, r0)
1366
1367 case ANEGF:
1368 opset(ANEGD, r0)
1369 opset(ASQRTF, r0)
1370 opset(ASQRTD, r0)
1371 opset(AMOVFD, r0)
1372 opset(AMOVDF, r0)
1373 opset(AABSF, r0)
1374 opset(AABSD, r0)
1375
1376 case ACMPF:
1377 opset(ACMPD, r0)
1378
1379 case AMOVF:
1380 opset(AMOVD, r0)
1381
1382 case AMOVFW:
1383 opset(AMOVDW, r0)
1384
1385 case AMOVWF:
1386 opset(AMOVWD, r0)
1387
1388 case AMULL:
1389 opset(AMULAL, r0)
1390 opset(AMULLU, r0)
1391 opset(AMULALU, r0)
1392
1393 case AMULWT:
1394 opset(AMULWB, r0)
1395 opset(AMULBB, r0)
1396 opset(AMMUL, r0)
1397
1398 case AMULAWT:
1399 opset(AMULAWB, r0)
1400 opset(AMULABB, r0)
1401 opset(AMULS, r0)
1402 opset(AMMULA, r0)
1403 opset(AMMULS, r0)
1404
1405 case ABFX:
1406 opset(ABFXU, r0)
1407 opset(ABFC, r0)
1408 opset(ABFI, r0)
1409
1410 case ACLZ:
1411 opset(AREV, r0)
1412 opset(AREV16, r0)
1413 opset(AREVSH, r0)
1414 opset(ARBIT, r0)
1415
1416 case AXTAB:
1417 opset(AXTAH, r0)
1418 opset(AXTABU, r0)
1419 opset(AXTAHU, r0)
1420
1421 case ALDREX,
1422 ASTREX,
1423 ALDREXD,
1424 ASTREXD,
1425 ADMB,
1426 APLD,
1427 AAND,
1428 AMULA,
1429 obj.AUNDEF,
1430 obj.AFUNCDATA,
1431 obj.APCDATA,
1432 obj.ANOP:
1433 break
1434 }
1435 }
1436 }
1437
1438 func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
1439 c.printp = p
1440 o1 := uint32(0)
1441 o2 := uint32(0)
1442 o3 := uint32(0)
1443 o4 := uint32(0)
1444 o5 := uint32(0)
1445 o6 := uint32(0)
1446 if false {
1447 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
1448 }
1449 switch o.type_ {
1450 default:
1451 c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
1452
1453 case 0:
1454 if false {
1455 fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
1456 }
1457
1458 case 1:
1459 o1 = c.oprrr(p, p.As, int(p.Scond))
1460
1461 rf := int(p.From.Reg)
1462 rt := int(p.To.Reg)
1463 r := int(p.Reg)
1464 if p.To.Type == obj.TYPE_NONE {
1465 rt = 0
1466 }
1467 if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
1468 r = 0
1469 } else if r == 0 {
1470 r = rt
1471 }
1472 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1473
1474 case 2:
1475 c.aclass(&p.From)
1476
1477 o1 = c.oprrr(p, p.As, int(p.Scond))
1478 o1 |= uint32(immrot(uint32(c.instoffset)))
1479 rt := int(p.To.Reg)
1480 r := int(p.Reg)
1481 if p.To.Type == obj.TYPE_NONE {
1482 rt = 0
1483 }
1484 if p.As == AMOVW || p.As == AMVN {
1485 r = 0
1486 } else if r == 0 {
1487 r = rt
1488 }
1489 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1490
1491 case 106:
1492 c.aclass(&p.From)
1493 r := int(p.Reg)
1494 rt := int(p.To.Reg)
1495 if r == 0 {
1496 r = rt
1497 }
1498 x, y := immrot2a(uint32(c.instoffset))
1499 var as2 obj.As
1500 switch p.As {
1501 case AADD, ASUB, AORR, AEOR, ABIC:
1502 as2 = p.As
1503 case ARSB:
1504 as2 = AADD
1505 case AADC:
1506 as2 = AADD
1507 case ASBC:
1508 as2 = ASUB
1509 case ARSC:
1510 as2 = AADD
1511 default:
1512 c.ctxt.Diag("unknown second op for %v", p)
1513 }
1514 o1 = c.oprrr(p, p.As, int(p.Scond))
1515 o2 = c.oprrr(p, as2, int(p.Scond))
1516 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1517 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1518 o1 |= x
1519 o2 |= y
1520
1521 case 107:
1522 c.aclass(&p.From)
1523 r := int(p.Reg)
1524 rt := int(p.To.Reg)
1525 if r == 0 {
1526 r = rt
1527 }
1528 y, x := immrot2s(uint32(c.instoffset))
1529 var as2 obj.As
1530 switch p.As {
1531 case AADD:
1532 as2 = ASUB
1533 case ASUB:
1534 as2 = AADD
1535 case ARSB:
1536 as2 = ASUB
1537 case AADC:
1538 as2 = ASUB
1539 case ASBC:
1540 as2 = AADD
1541 case ARSC:
1542 as2 = ASUB
1543 default:
1544 c.ctxt.Diag("unknown second op for %v", p)
1545 }
1546 o1 = c.oprrr(p, p.As, int(p.Scond))
1547 o2 = c.oprrr(p, as2, int(p.Scond))
1548 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
1549 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
1550 o1 |= y
1551 o2 |= x
1552
1553 case 3:
1554 o1 = c.mov(p)
1555
1556 case 4:
1557 c.aclass(&p.From)
1558 if c.instoffset < 0 {
1559 o1 = c.oprrr(p, ASUB, int(p.Scond))
1560 o1 |= uint32(immrot(uint32(-c.instoffset)))
1561 } else {
1562 o1 = c.oprrr(p, AADD, int(p.Scond))
1563 o1 |= uint32(immrot(uint32(c.instoffset)))
1564 }
1565 r := int(p.From.Reg)
1566 if r == 0 {
1567 r = int(o.param)
1568 }
1569 o1 |= (uint32(r) & 15) << 16
1570 o1 |= (uint32(p.To.Reg) & 15) << 12
1571
1572 case 5:
1573 o1 = c.opbra(p, p.As, int(p.Scond))
1574
1575 v := int32(-8)
1576 if p.To.Sym != nil {
1577 rel := obj.Addrel(c.cursym)
1578 rel.Off = int32(c.pc)
1579 rel.Siz = 4
1580 rel.Sym = p.To.Sym
1581 v += int32(p.To.Offset)
1582 rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
1583 rel.Type = objabi.R_CALLARM
1584 break
1585 }
1586
1587 if p.To.Target() != nil {
1588 v = int32((p.To.Target().Pc - c.pc) - 8)
1589 }
1590 o1 |= (uint32(v) >> 2) & 0xffffff
1591
1592 case 6:
1593 c.aclass(&p.To)
1594
1595 o1 = c.oprrr(p, AADD, int(p.Scond))
1596 o1 |= uint32(immrot(uint32(c.instoffset)))
1597 o1 |= (uint32(p.To.Reg) & 15) << 16
1598 o1 |= (REGPC & 15) << 12
1599
1600 case 7:
1601 c.aclass(&p.To)
1602
1603 if c.instoffset != 0 {
1604 c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
1605 }
1606 o1 = c.oprrr(p, ABL, int(p.Scond))
1607 o1 |= (uint32(p.To.Reg) & 15) << 0
1608 rel := obj.Addrel(c.cursym)
1609 rel.Off = int32(c.pc)
1610 rel.Siz = 0
1611 rel.Type = objabi.R_CALLIND
1612
1613 case 8:
1614 c.aclass(&p.From)
1615
1616 o1 = c.oprrr(p, p.As, int(p.Scond))
1617 r := int(p.Reg)
1618 if r == 0 {
1619 r = int(p.To.Reg)
1620 }
1621 o1 |= (uint32(r) & 15) << 0
1622 o1 |= uint32((c.instoffset & 31) << 7)
1623 o1 |= (uint32(p.To.Reg) & 15) << 12
1624
1625 case 9:
1626 o1 = c.oprrr(p, p.As, int(p.Scond))
1627
1628 r := int(p.Reg)
1629 if r == 0 {
1630 r = int(p.To.Reg)
1631 }
1632 o1 |= (uint32(r) & 15) << 0
1633 o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
1634 o1 |= (uint32(p.To.Reg) & 15) << 12
1635
1636 case 10:
1637 o1 = c.oprrr(p, p.As, int(p.Scond))
1638
1639 if p.To.Type != obj.TYPE_NONE {
1640 c.aclass(&p.To)
1641 o1 |= uint32(c.instoffset & 0xffffff)
1642 }
1643
1644 case 11:
1645 c.aclass(&p.To)
1646
1647 o1 = uint32(c.instoffset)
1648 if p.To.Sym != nil {
1649
1650
1651 rel := obj.Addrel(c.cursym)
1652
1653 rel.Off = int32(c.pc)
1654 rel.Siz = 4
1655 rel.Sym = p.To.Sym
1656 rel.Add = p.To.Offset
1657
1658 if c.ctxt.Flag_shared {
1659 if p.To.Name == obj.NAME_GOTREF {
1660 rel.Type = objabi.R_GOTPCREL
1661 } else {
1662 rel.Type = objabi.R_PCREL
1663 }
1664 rel.Add += c.pc - p.Rel.Pc - 8
1665 } else {
1666 rel.Type = objabi.R_ADDR
1667 }
1668 o1 = 0
1669 }
1670
1671 case 12:
1672 if o.a1 == C_SCON {
1673 o1 = c.omvs(p, &p.From, int(p.To.Reg))
1674 } else if p.As == AMVN {
1675 o1 = c.omvr(p, &p.From, int(p.To.Reg))
1676 } else {
1677 o1 = c.omvl(p, &p.From, int(p.To.Reg))
1678 }
1679
1680 if o.flag&LPCREL != 0 {
1681 o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
1682 }
1683
1684 case 13:
1685 if o.a1 == C_SCON {
1686 o1 = c.omvs(p, &p.From, REGTMP)
1687 } else {
1688 o1 = c.omvl(p, &p.From, REGTMP)
1689 }
1690
1691 if o1 == 0 {
1692 break
1693 }
1694 o2 = c.oprrr(p, p.As, int(p.Scond))
1695 o2 |= REGTMP & 15
1696 r := int(p.Reg)
1697 if p.As == AMVN {
1698 r = 0
1699 } else if r == 0 {
1700 r = int(p.To.Reg)
1701 }
1702 o2 |= (uint32(r) & 15) << 16
1703 if p.To.Type != obj.TYPE_NONE {
1704 o2 |= (uint32(p.To.Reg) & 15) << 12
1705 }
1706
1707 case 14:
1708 o1 = c.oprrr(p, ASLL, int(p.Scond))
1709
1710 if p.As == AMOVBU || p.As == AMOVHU {
1711 o2 = c.oprrr(p, ASRL, int(p.Scond))
1712 } else {
1713 o2 = c.oprrr(p, ASRA, int(p.Scond))
1714 }
1715
1716 r := int(p.To.Reg)
1717 o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
1718 o2 |= uint32(r)&15 | (uint32(r)&15)<<12
1719 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
1720 o1 |= 24 << 7
1721 o2 |= 24 << 7
1722 } else {
1723 o1 |= 16 << 7
1724 o2 |= 16 << 7
1725 }
1726
1727 case 15:
1728 o1 = c.oprrr(p, p.As, int(p.Scond))
1729
1730 rf := int(p.From.Reg)
1731 rt := int(p.To.Reg)
1732 r := int(p.Reg)
1733 if r == 0 {
1734 r = rt
1735 }
1736
1737 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
1738
1739 case 16:
1740 o1 = 0xf << 28
1741
1742 o2 = 0
1743
1744 case 17:
1745 o1 = c.oprrr(p, p.As, int(p.Scond))
1746 rf := int(p.From.Reg)
1747 rt := int(p.To.Reg)
1748 rt2 := int(p.To.Offset)
1749 r := int(p.Reg)
1750 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
1751
1752 case 18:
1753 o1 = c.oprrr(p, p.As, int(p.Scond))
1754 rt := int(p.To.Reg)
1755 r := int(p.Reg)
1756 if r == 0 {
1757 r = rt
1758 } else if p.As == ABFC {
1759 c.ctxt.Diag("illegal combination: %v", p)
1760 }
1761 if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
1762 c.ctxt.Diag("%v: missing or wrong LSB", p)
1763 break
1764 }
1765 lsb := p.GetFrom3().Offset
1766 width := p.From.Offset
1767 if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
1768 c.ctxt.Diag("%v: wrong width or LSB", p)
1769 }
1770 switch p.As {
1771 case ABFX, ABFXU:
1772 o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
1773 case ABFC, ABFI:
1774 o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
1775 default:
1776 c.ctxt.Diag("illegal combination: %v", p)
1777 }
1778
1779 case 20:
1780 c.aclass(&p.To)
1781
1782 r := int(p.To.Reg)
1783 if r == 0 {
1784 r = int(o.param)
1785 }
1786 o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
1787
1788 case 21:
1789 c.aclass(&p.From)
1790
1791 r := int(p.From.Reg)
1792 if r == 0 {
1793 r = int(o.param)
1794 }
1795 o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
1796 if p.As != AMOVW {
1797 o1 |= 1 << 22
1798 }
1799
1800 case 22:
1801 o1 = c.oprrr(p, p.As, int(p.Scond))
1802 switch p.From.Offset &^ 0xf {
1803
1804 case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
1805 o1 |= uint32(p.From.Offset) & 0xc0f
1806 default:
1807 c.ctxt.Diag("illegal shift: %v", p)
1808 }
1809 rt := p.To.Reg
1810 r := p.Reg
1811 if r == 0 {
1812 r = rt
1813 }
1814 o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
1815
1816 case 23:
1817 switch p.As {
1818 case AMOVW:
1819 o1 = c.mov(p)
1820 case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
1821 o1 = c.movxt(p)
1822 default:
1823 c.ctxt.Diag("illegal combination: %v", p)
1824 }
1825
1826 case 30:
1827 o1 = c.omvl(p, &p.To, REGTMP)
1828
1829 if o1 == 0 {
1830 break
1831 }
1832 r := int(p.To.Reg)
1833 if r == 0 {
1834 r = int(o.param)
1835 }
1836 o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
1837 if p.As != AMOVW {
1838 o2 |= 1 << 22
1839 }
1840
1841 case 31:
1842 o1 = c.omvl(p, &p.From, REGTMP)
1843
1844 if o1 == 0 {
1845 break
1846 }
1847 r := int(p.From.Reg)
1848 if r == 0 {
1849 r = int(o.param)
1850 }
1851 o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
1852 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
1853 o2 |= 1 << 22
1854 }
1855
1856 case 34:
1857 o1 = c.omvl(p, &p.From, REGTMP)
1858
1859 if o1 == 0 {
1860 break
1861 }
1862
1863 o2 = c.oprrr(p, AADD, int(p.Scond))
1864 o2 |= REGTMP & 15
1865 r := int(p.From.Reg)
1866 if r == 0 {
1867 r = int(o.param)
1868 }
1869 o2 |= (uint32(r) & 15) << 16
1870 if p.To.Type != obj.TYPE_NONE {
1871 o2 |= (uint32(p.To.Reg) & 15) << 12
1872 }
1873
1874 case 35:
1875 o1 = 2<<23 | 0xf<<16 | 0<<0
1876
1877 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1878 o1 |= (uint32(p.From.Reg) & 1) << 22
1879 o1 |= (uint32(p.To.Reg) & 15) << 12
1880
1881 case 36:
1882 o1 = 2<<23 | 0x2cf<<12 | 0<<4
1883
1884 if p.Scond&C_FBIT != 0 {
1885 o1 ^= 0x010 << 12
1886 }
1887 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1888 o1 |= (uint32(p.To.Reg) & 1) << 22
1889 o1 |= (uint32(p.From.Reg) & 15) << 0
1890
1891 case 37:
1892 c.aclass(&p.From)
1893
1894 o1 = 2<<23 | 0x2cf<<12 | 0<<4
1895 if p.Scond&C_FBIT != 0 {
1896 o1 ^= 0x010 << 12
1897 }
1898 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1899 o1 |= uint32(immrot(uint32(c.instoffset)))
1900 o1 |= (uint32(p.To.Reg) & 1) << 22
1901 o1 |= (uint32(p.From.Reg) & 15) << 0
1902
1903 case 38, 39:
1904 switch o.type_ {
1905 case 38:
1906 o1 = 0x4 << 25
1907
1908 o1 |= uint32(p.From.Offset & 0xffff)
1909 o1 |= (uint32(p.To.Reg) & 15) << 16
1910 c.aclass(&p.To)
1911
1912 case 39:
1913 o1 = 0x4<<25 | 1<<20
1914
1915 o1 |= uint32(p.To.Offset & 0xffff)
1916 o1 |= (uint32(p.From.Reg) & 15) << 16
1917 c.aclass(&p.From)
1918 }
1919
1920 if c.instoffset != 0 {
1921 c.ctxt.Diag("offset must be zero in MOVM; %v", p)
1922 }
1923 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1924 if p.Scond&C_PBIT != 0 {
1925 o1 |= 1 << 24
1926 }
1927 if p.Scond&C_UBIT != 0 {
1928 o1 |= 1 << 23
1929 }
1930 if p.Scond&C_WBIT != 0 {
1931 o1 |= 1 << 21
1932 }
1933
1934 case 40:
1935 c.aclass(&p.From)
1936
1937 if c.instoffset != 0 {
1938 c.ctxt.Diag("offset must be zero in SWP")
1939 }
1940 o1 = 0x2<<23 | 0x9<<4
1941 if p.As != ASWPW {
1942 o1 |= 1 << 22
1943 }
1944 o1 |= (uint32(p.From.Reg) & 15) << 16
1945 o1 |= (uint32(p.Reg) & 15) << 0
1946 o1 |= (uint32(p.To.Reg) & 15) << 12
1947 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
1948
1949 case 41:
1950 o1 = 0xe8fd8000
1951
1952 case 50:
1953 v := c.regoff(&p.To)
1954
1955 r := int(p.To.Reg)
1956 if r == 0 {
1957 r = int(o.param)
1958 }
1959 o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
1960
1961 case 51:
1962 v := c.regoff(&p.From)
1963
1964 r := int(p.From.Reg)
1965 if r == 0 {
1966 r = int(o.param)
1967 }
1968 o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
1969
1970 case 52:
1971 o1 = c.omvl(p, &p.To, REGTMP)
1972
1973 if o1 == 0 {
1974 break
1975 }
1976 r := int(p.To.Reg)
1977 if r == 0 {
1978 r = int(o.param)
1979 }
1980 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
1981 o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
1982
1983 case 53:
1984 o1 = c.omvl(p, &p.From, REGTMP)
1985
1986 if o1 == 0 {
1987 break
1988 }
1989 r := int(p.From.Reg)
1990 if r == 0 {
1991 r = int(o.param)
1992 }
1993 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
1994 o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
1995
1996 case 54:
1997 o1 = c.oprrr(p, p.As, int(p.Scond))
1998
1999 rf := int(p.From.Reg)
2000 rt := int(p.To.Reg)
2001 r := int(p.Reg)
2002 if r == 0 {
2003 switch p.As {
2004 case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
2005 AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
2006 c.ctxt.Diag("illegal combination: %v", p)
2007 default:
2008 r = rt
2009 }
2010 }
2011
2012 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2013
2014 case 55:
2015 o1 = c.oprrr(p, p.As, int(p.Scond))
2016
2017 rf := int(p.From.Reg)
2018 rt := int(p.To.Reg)
2019
2020 o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
2021
2022 case 56:
2023 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
2024
2025 o1 |= (uint32(p.From.Reg) & 15) << 12
2026
2027 case 57:
2028 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
2029
2030 o1 |= (uint32(p.To.Reg) & 15) << 12
2031
2032 case 58:
2033 o1 = c.oprrr(p, AAND, int(p.Scond))
2034
2035 o1 |= uint32(immrot(0xff))
2036 rt := int(p.To.Reg)
2037 r := int(p.From.Reg)
2038 if p.To.Type == obj.TYPE_NONE {
2039 rt = 0
2040 }
2041 if r == 0 {
2042 r = rt
2043 }
2044 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2045
2046 case 59:
2047 if p.From.Reg == 0 {
2048 c.ctxt.Diag("source operand is not a memory address: %v", p)
2049 break
2050 }
2051 if p.From.Offset&(1<<4) != 0 {
2052 c.ctxt.Diag("bad shift in LDR")
2053 break
2054 }
2055 o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2056 if p.As == AMOVBU {
2057 o1 |= 1 << 22
2058 }
2059
2060 case 60:
2061 if p.From.Reg == 0 {
2062 c.ctxt.Diag("source operand is not a memory address: %v", p)
2063 break
2064 }
2065 if p.From.Offset&(^0xf) != 0 {
2066 c.ctxt.Diag("bad shift: %v", p)
2067 break
2068 }
2069 o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
2070 switch p.As {
2071 case AMOVB, AMOVBS:
2072 o1 ^= 1<<5 | 1<<6
2073 case AMOVH, AMOVHS:
2074 o1 ^= 1 << 6
2075 default:
2076 }
2077 if p.Scond&C_UBIT != 0 {
2078 o1 &^= 1 << 23
2079 }
2080
2081 case 61:
2082 if p.To.Reg == 0 {
2083 c.ctxt.Diag("MOV to shifter operand")
2084 }
2085 o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
2086 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
2087 o1 |= 1 << 22
2088 }
2089
2090 case 62:
2091 if p.To.Reg == 0 {
2092 c.ctxt.Diag("MOV to shifter operand")
2093 }
2094 if p.To.Offset&(^0xf) != 0 {
2095 c.ctxt.Diag("bad shift: %v", p)
2096 }
2097 o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
2098 o1 ^= 1 << 20
2099 if p.Scond&C_UBIT != 0 {
2100 o1 &^= 1 << 23
2101 }
2102
2103
2104 case 64:
2105 o1 = c.omvl(p, &p.To, REGTMP)
2106
2107 if o1 == 0 {
2108 break
2109 }
2110 o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
2111 if o.flag&LPCREL != 0 {
2112 o3 = o2
2113 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2114 }
2115
2116 case 65:
2117 o1 = c.omvl(p, &p.From, REGTMP)
2118
2119 if o1 == 0 {
2120 break
2121 }
2122 o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2123 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
2124 o2 |= 1 << 22
2125 }
2126 if o.flag&LPCREL != 0 {
2127 o3 = o2
2128 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2129 }
2130
2131 case 101:
2132 o1 = c.omvl(p, &p.From, int(p.To.Reg))
2133
2134 case 102:
2135 o1 = c.omvl(p, &p.From, int(p.To.Reg))
2136 o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
2137
2138 case 103:
2139 if p.To.Sym == nil {
2140 c.ctxt.Diag("nil sym in tls %v", p)
2141 }
2142 if p.To.Offset != 0 {
2143 c.ctxt.Diag("offset against tls var in %v", p)
2144 }
2145
2146
2147 rel := obj.Addrel(c.cursym)
2148
2149 rel.Off = int32(c.pc)
2150 rel.Siz = 4
2151 rel.Sym = p.To.Sym
2152 rel.Type = objabi.R_TLS_LE
2153 o1 = 0
2154
2155 case 104:
2156 if p.To.Sym == nil {
2157 c.ctxt.Diag("nil sym in tls %v", p)
2158 }
2159 if p.To.Offset != 0 {
2160 c.ctxt.Diag("offset against tls var in %v", p)
2161 }
2162 rel := obj.Addrel(c.cursym)
2163 rel.Off = int32(c.pc)
2164 rel.Siz = 4
2165 rel.Sym = p.To.Sym
2166 rel.Type = objabi.R_TLS_IE
2167 rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
2168
2169 case 68:
2170 o1 = c.omvl(p, &p.To, REGTMP)
2171
2172 if o1 == 0 {
2173 break
2174 }
2175 o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
2176 if o.flag&LPCREL != 0 {
2177 o3 = o2
2178 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2179 }
2180
2181 case 69:
2182 o1 = c.omvl(p, &p.From, REGTMP)
2183
2184 if o1 == 0 {
2185 break
2186 }
2187 o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
2188 if o.flag&LPCREL != 0 {
2189 o3 = o2
2190 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2191 }
2192
2193
2194 case 70:
2195 c.aclass(&p.To)
2196
2197 r := int(p.To.Reg)
2198 if r == 0 {
2199 r = int(o.param)
2200 }
2201 o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
2202
2203 case 71:
2204 c.aclass(&p.From)
2205
2206 r := int(p.From.Reg)
2207 if r == 0 {
2208 r = int(o.param)
2209 }
2210 o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
2211 if p.As == AMOVB || p.As == AMOVBS {
2212 o1 ^= 1<<5 | 1<<6
2213 } else if p.As == AMOVH || p.As == AMOVHS {
2214 o1 ^= (1 << 6)
2215 }
2216
2217 case 72:
2218 o1 = c.omvl(p, &p.To, REGTMP)
2219
2220 if o1 == 0 {
2221 break
2222 }
2223 r := int(p.To.Reg)
2224 if r == 0 {
2225 r = int(o.param)
2226 }
2227 o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
2228
2229 case 73:
2230 o1 = c.omvl(p, &p.From, REGTMP)
2231
2232 if o1 == 0 {
2233 break
2234 }
2235 r := int(p.From.Reg)
2236 if r == 0 {
2237 r = int(o.param)
2238 }
2239 o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
2240 if p.As == AMOVB || p.As == AMOVBS {
2241 o2 ^= 1<<5 | 1<<6
2242 } else if p.As == AMOVH || p.As == AMOVHS {
2243 o2 ^= (1 << 6)
2244 }
2245
2246 case 74:
2247 c.ctxt.Diag("ABX $I")
2248
2249 case 75:
2250 c.aclass(&p.To)
2251
2252 if c.instoffset != 0 {
2253 c.ctxt.Diag("non-zero offset in ABX")
2254 }
2255
2256
2260
2261 o1 = c.oprrr(p, AADD, int(p.Scond))
2262
2263 o1 |= uint32(immrot(uint32(c.instoffset)))
2264 o1 |= (uint32(p.To.Reg) & 15) << 16
2265 o1 |= (REGTMP & 15) << 12
2266 o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12
2267 o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15
2268
2269 case 76:
2270 c.ctxt.Diag("ABXRET")
2271
2272 case 77:
2273 c.aclass(&p.From)
2274
2275 if c.instoffset != 0 {
2276 c.ctxt.Diag("offset must be zero in LDREX")
2277 }
2278 o1 = 0x19<<20 | 0xf9f
2279 o1 |= (uint32(p.From.Reg) & 15) << 16
2280 o1 |= (uint32(p.To.Reg) & 15) << 12
2281 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2282
2283 case 78:
2284 c.aclass(&p.From)
2285
2286 if c.instoffset != 0 {
2287 c.ctxt.Diag("offset must be zero in STREX")
2288 }
2289 if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
2290 c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2291 }
2292 o1 = 0x18<<20 | 0xf90
2293 o1 |= (uint32(p.From.Reg) & 15) << 16
2294 o1 |= (uint32(p.Reg) & 15) << 0
2295 o1 |= (uint32(p.To.Reg) & 15) << 12
2296 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2297
2298 case 80:
2299 if p.As == AMOVD {
2300 o1 = 0xeeb00b00
2301 o2 = c.oprrr(p, ASUBD, int(p.Scond))
2302 } else {
2303 o1 = 0x0eb00a00
2304 o2 = c.oprrr(p, ASUBF, int(p.Scond))
2305 }
2306
2307 v := int32(0x70)
2308 r := (int(p.To.Reg) & 15) << 0
2309
2310
2311 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2312
2313 o1 |= (uint32(r) & 15) << 12
2314 o1 |= (uint32(v) & 0xf) << 0
2315 o1 |= (uint32(v) & 0xf0) << 12
2316
2317
2318 o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
2319
2320 case 81:
2321 o1 = 0x0eb00a00
2322 if p.As == AMOVD {
2323 o1 = 0xeeb00b00
2324 }
2325 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2326 o1 |= (uint32(p.To.Reg) & 15) << 12
2327 v := int32(c.chipfloat5(p.From.Val.(float64)))
2328 o1 |= (uint32(v) & 0xf) << 0
2329 o1 |= (uint32(v) & 0xf0) << 12
2330
2331 case 82:
2332 o1 = c.oprrr(p, p.As, int(p.Scond))
2333
2334 o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
2335 o2 = 0x0ef1fa10
2336 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2337
2338 case 83:
2339 o1 = c.oprrr(p, p.As, int(p.Scond))
2340
2341 o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
2342 o2 = 0x0ef1fa10
2343 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2344
2345 case 84:
2346 o1 = c.oprrr(p, p.As, int(p.Scond))
2347
2348 o1 |= (uint32(p.From.Reg) & 15) << 0
2349 o1 |= (uint32(p.To.Reg) & 15) << 12
2350
2351 case 85:
2352 o1 = c.oprrr(p, p.As, int(p.Scond))
2353
2354 o1 |= (uint32(p.From.Reg) & 15) << 0
2355 o1 |= (uint32(p.To.Reg) & 15) << 12
2356
2357
2358 case 86:
2359 o1 = c.oprrr(p, p.As, int(p.Scond))
2360
2361 o1 |= (uint32(p.From.Reg) & 15) << 0
2362 o1 |= (FREGTMP & 15) << 12
2363 o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
2364 o2 |= (FREGTMP & 15) << 16
2365 o2 |= (uint32(p.To.Reg) & 15) << 12
2366
2367
2368 case 87:
2369 o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2370
2371 o1 |= (uint32(p.From.Reg) & 15) << 12
2372 o1 |= (FREGTMP & 15) << 16
2373 o2 = c.oprrr(p, p.As, int(p.Scond))
2374 o2 |= (FREGTMP & 15) << 0
2375 o2 |= (uint32(p.To.Reg) & 15) << 12
2376
2377 case 88:
2378 o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
2379
2380 o1 |= (uint32(p.From.Reg) & 15) << 12
2381 o1 |= (uint32(p.To.Reg) & 15) << 16
2382
2383 case 89:
2384 o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
2385
2386 o1 |= (uint32(p.From.Reg) & 15) << 16
2387 o1 |= (uint32(p.To.Reg) & 15) << 12
2388
2389 case 91:
2390 c.aclass(&p.From)
2391
2392 if c.instoffset != 0 {
2393 c.ctxt.Diag("offset must be zero in LDREX")
2394 }
2395 o1 = 0x1b<<20 | 0xf9f
2396 o1 |= (uint32(p.From.Reg) & 15) << 16
2397 o1 |= (uint32(p.To.Reg) & 15) << 12
2398 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2399
2400 case 92:
2401 c.aclass(&p.From)
2402
2403 if c.instoffset != 0 {
2404 c.ctxt.Diag("offset must be zero in STREX")
2405 }
2406 if p.Reg&1 != 0 {
2407 c.ctxt.Diag("source register must be even in STREXD: %v", p)
2408 }
2409 if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
2410 c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
2411 }
2412 o1 = 0x1a<<20 | 0xf90
2413 o1 |= (uint32(p.From.Reg) & 15) << 16
2414 o1 |= (uint32(p.Reg) & 15) << 0
2415 o1 |= (uint32(p.To.Reg) & 15) << 12
2416 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2417
2418 case 93:
2419 o1 = c.omvl(p, &p.From, REGTMP)
2420
2421 if o1 == 0 {
2422 break
2423 }
2424 o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
2425 if p.As == AMOVB || p.As == AMOVBS {
2426 o2 ^= 1<<5 | 1<<6
2427 } else if p.As == AMOVH || p.As == AMOVHS {
2428 o2 ^= (1 << 6)
2429 }
2430 if o.flag&LPCREL != 0 {
2431 o3 = o2
2432 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2433 }
2434
2435 case 94:
2436 o1 = c.omvl(p, &p.To, REGTMP)
2437
2438 if o1 == 0 {
2439 break
2440 }
2441 o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
2442 if o.flag&LPCREL != 0 {
2443 o3 = o2
2444 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
2445 }
2446
2447 case 95:
2448 o1 = 0xf5d0f000
2449
2450 o1 |= (uint32(p.From.Reg) & 15) << 16
2451 if p.From.Offset < 0 {
2452 o1 &^= (1 << 23)
2453 o1 |= uint32((-p.From.Offset) & 0xfff)
2454 } else {
2455 o1 |= uint32(p.From.Offset & 0xfff)
2456 }
2457
2458
2459
2460
2461
2462
2463 case 96:
2464 o1 = 0xf7fabcfd
2465
2466 case 97:
2467 o1 = c.oprrr(p, p.As, int(p.Scond))
2468
2469 o1 |= (uint32(p.To.Reg) & 15) << 12
2470 o1 |= (uint32(p.From.Reg) & 15) << 0
2471
2472 case 98:
2473 o1 = c.oprrr(p, p.As, int(p.Scond))
2474
2475 o1 |= (uint32(p.To.Reg) & 15) << 16
2476 o1 |= (uint32(p.From.Reg) & 15) << 8
2477 o1 |= (uint32(p.Reg) & 15) << 0
2478
2479 case 99:
2480 o1 = c.oprrr(p, p.As, int(p.Scond))
2481
2482 o1 |= (uint32(p.To.Reg) & 15) << 16
2483 o1 |= (uint32(p.From.Reg) & 15) << 8
2484 o1 |= (uint32(p.Reg) & 15) << 0
2485 o1 |= uint32((p.To.Offset & 15) << 12)
2486
2487 case 105:
2488 o1 = c.oprrr(p, p.As, int(p.Scond))
2489 rf := int(p.From.Reg)
2490 rt := int(p.To.Reg)
2491 r := int(p.Reg)
2492 if r == 0 {
2493 r = rt
2494 }
2495 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
2496
2497 case 110:
2498 o1 = 0xf57ff050
2499 mbop := uint32(0)
2500
2501 switch c.aclass(&p.From) {
2502 case C_SPR:
2503 for _, f := range mbOp {
2504 if f.reg == p.From.Reg {
2505 mbop = f.enc
2506 break
2507 }
2508 }
2509 case C_RCON:
2510 for _, f := range mbOp {
2511 enc := uint32(c.instoffset)
2512 if f.enc == enc {
2513 mbop = enc
2514 break
2515 }
2516 }
2517 case C_NONE:
2518 mbop = 0xf
2519 }
2520
2521 if mbop == 0 {
2522 c.ctxt.Diag("illegal mb option:\n%v", p)
2523 }
2524 o1 |= mbop
2525 }
2526
2527 out[0] = o1
2528 out[1] = o2
2529 out[2] = o3
2530 out[3] = o4
2531 out[4] = o5
2532 out[5] = o6
2533 }
2534
2535 func (c *ctxt5) movxt(p *obj.Prog) uint32 {
2536 o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
2537 switch p.As {
2538 case AMOVB, AMOVBS:
2539 o1 |= 0x6af<<16 | 0x7<<4
2540 case AMOVH, AMOVHS:
2541 o1 |= 0x6bf<<16 | 0x7<<4
2542 case AMOVBU:
2543 o1 |= 0x6ef<<16 | 0x7<<4
2544 case AMOVHU:
2545 o1 |= 0x6ff<<16 | 0x7<<4
2546 default:
2547 c.ctxt.Diag("illegal combination: %v", p)
2548 }
2549 switch p.From.Offset &^ 0xf {
2550
2551 case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
2552 o1 |= uint32(p.From.Offset) & 0xc0f
2553 default:
2554 c.ctxt.Diag("illegal shift: %v", p)
2555 }
2556 o1 |= (uint32(p.To.Reg) & 15) << 12
2557 return o1
2558 }
2559
2560 func (c *ctxt5) mov(p *obj.Prog) uint32 {
2561 c.aclass(&p.From)
2562 o1 := c.oprrr(p, p.As, int(p.Scond))
2563 o1 |= uint32(p.From.Offset)
2564 rt := int(p.To.Reg)
2565 if p.To.Type == obj.TYPE_NONE {
2566 rt = 0
2567 }
2568 r := int(p.Reg)
2569 if p.As == AMOVW || p.As == AMVN {
2570 r = 0
2571 } else if r == 0 {
2572 r = rt
2573 }
2574 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
2575 return o1
2576 }
2577
2578 func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
2579 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2580 if sc&C_SBIT != 0 {
2581 o |= 1 << 20
2582 }
2583 switch a {
2584 case ADIVHW:
2585 return o | 0x71<<20 | 0xf<<12 | 0x1<<4
2586 case ADIVUHW:
2587 return o | 0x73<<20 | 0xf<<12 | 0x1<<4
2588 case AMMUL:
2589 return o | 0x75<<20 | 0xf<<12 | 0x1<<4
2590 case AMULS:
2591 return o | 0x6<<20 | 0x9<<4
2592 case AMMULA:
2593 return o | 0x75<<20 | 0x1<<4
2594 case AMMULS:
2595 return o | 0x75<<20 | 0xd<<4
2596 case AMULU, AMUL:
2597 return o | 0x0<<21 | 0x9<<4
2598 case AMULA:
2599 return o | 0x1<<21 | 0x9<<4
2600 case AMULLU:
2601 return o | 0x4<<21 | 0x9<<4
2602 case AMULL:
2603 return o | 0x6<<21 | 0x9<<4
2604 case AMULALU:
2605 return o | 0x5<<21 | 0x9<<4
2606 case AMULAL:
2607 return o | 0x7<<21 | 0x9<<4
2608 case AAND:
2609 return o | 0x0<<21
2610 case AEOR:
2611 return o | 0x1<<21
2612 case ASUB:
2613 return o | 0x2<<21
2614 case ARSB:
2615 return o | 0x3<<21
2616 case AADD:
2617 return o | 0x4<<21
2618 case AADC:
2619 return o | 0x5<<21
2620 case ASBC:
2621 return o | 0x6<<21
2622 case ARSC:
2623 return o | 0x7<<21
2624 case ATST:
2625 return o | 0x8<<21 | 1<<20
2626 case ATEQ:
2627 return o | 0x9<<21 | 1<<20
2628 case ACMP:
2629 return o | 0xa<<21 | 1<<20
2630 case ACMN:
2631 return o | 0xb<<21 | 1<<20
2632 case AORR:
2633 return o | 0xc<<21
2634
2635 case AMOVB, AMOVH, AMOVW:
2636 if sc&(C_PBIT|C_WBIT) != 0 {
2637 c.ctxt.Diag("invalid .P/.W suffix: %v", p)
2638 }
2639 return o | 0xd<<21
2640 case ABIC:
2641 return o | 0xe<<21
2642 case AMVN:
2643 return o | 0xf<<21
2644 case ASLL:
2645 return o | 0xd<<21 | 0<<5
2646 case ASRL:
2647 return o | 0xd<<21 | 1<<5
2648 case ASRA:
2649 return o | 0xd<<21 | 2<<5
2650 case ASWI:
2651 return o | 0xf<<24
2652
2653 case AADDD:
2654 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
2655 case AADDF:
2656 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
2657 case ASUBD:
2658 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
2659 case ASUBF:
2660 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
2661 case AMULD:
2662 return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
2663 case AMULF:
2664 return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
2665 case ANMULD:
2666 return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
2667 case ANMULF:
2668 return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
2669 case AMULAD:
2670 return o | 0xe<<24 | 0xb<<8
2671 case AMULAF:
2672 return o | 0xe<<24 | 0xa<<8
2673 case AMULSD:
2674 return o | 0xe<<24 | 0xb<<8 | 0x4<<4
2675 case AMULSF:
2676 return o | 0xe<<24 | 0xa<<8 | 0x4<<4
2677 case ANMULAD:
2678 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
2679 case ANMULAF:
2680 return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
2681 case ANMULSD:
2682 return o | 0xe<<24 | 0x1<<20 | 0xb<<8
2683 case ANMULSF:
2684 return o | 0xe<<24 | 0x1<<20 | 0xa<<8
2685 case AFMULAD:
2686 return o | 0xe<<24 | 0xa<<20 | 0xb<<8
2687 case AFMULAF:
2688 return o | 0xe<<24 | 0xa<<20 | 0xa<<8
2689 case AFMULSD:
2690 return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
2691 case AFMULSF:
2692 return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
2693 case AFNMULAD:
2694 return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
2695 case AFNMULAF:
2696 return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
2697 case AFNMULSD:
2698 return o | 0xe<<24 | 0x9<<20 | 0xb<<8
2699 case AFNMULSF:
2700 return o | 0xe<<24 | 0x9<<20 | 0xa<<8
2701 case ADIVD:
2702 return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
2703 case ADIVF:
2704 return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
2705 case ASQRTD:
2706 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
2707 case ASQRTF:
2708 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
2709 case AABSD:
2710 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
2711 case AABSF:
2712 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
2713 case ANEGD:
2714 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
2715 case ANEGF:
2716 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
2717 case ACMPD:
2718 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
2719 case ACMPF:
2720 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
2721
2722 case AMOVF:
2723 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
2724 case AMOVD:
2725 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
2726
2727 case AMOVDF:
2728 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8
2729 case AMOVFD:
2730 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8
2731
2732 case AMOVWF:
2733 if sc&C_UBIT == 0 {
2734 o |= 1 << 7
2735 }
2736 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8
2737
2738 case AMOVWD:
2739 if sc&C_UBIT == 0 {
2740 o |= 1 << 7
2741 }
2742 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8
2743
2744 case AMOVFW:
2745 if sc&C_UBIT == 0 {
2746 o |= 1 << 16
2747 }
2748 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7
2749
2750 case AMOVDW:
2751 if sc&C_UBIT == 0 {
2752 o |= 1 << 16
2753 }
2754 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7
2755
2756 case -AMOVWF:
2757 return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
2758
2759 case -AMOVFW:
2760 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
2761
2762 case -ACMP:
2763 return o | 0x3<<24 | 0x5<<20
2764
2765 case ABFX:
2766 return o | 0x3d<<21 | 0x5<<4
2767
2768 case ABFXU:
2769 return o | 0x3f<<21 | 0x5<<4
2770
2771 case ABFC:
2772 return o | 0x3e<<21 | 0x1f
2773
2774 case ABFI:
2775 return o | 0x3e<<21 | 0x1<<4
2776
2777 case AXTAB:
2778 return o | 0x6a<<20 | 0x7<<4
2779
2780 case AXTAH:
2781 return o | 0x6b<<20 | 0x7<<4
2782
2783 case AXTABU:
2784 return o | 0x6e<<20 | 0x7<<4
2785
2786 case AXTAHU:
2787 return o | 0x6f<<20 | 0x7<<4
2788
2789
2790 case ACLZ:
2791 return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
2792
2793 case AREV:
2794 return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
2795
2796 case AREV16:
2797 return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
2798
2799 case AREVSH:
2800 return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
2801
2802 case ARBIT:
2803 return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
2804
2805 case AMULWT:
2806 return o&(0xf<<28) | 0x12<<20 | 0xe<<4
2807
2808 case AMULWB:
2809 return o&(0xf<<28) | 0x12<<20 | 0xa<<4
2810
2811 case AMULBB:
2812 return o&(0xf<<28) | 0x16<<20 | 0x8<<4
2813
2814 case AMULAWT:
2815 return o&(0xf<<28) | 0x12<<20 | 0xc<<4
2816
2817 case AMULAWB:
2818 return o&(0xf<<28) | 0x12<<20 | 0x8<<4
2819
2820 case AMULABB:
2821 return o&(0xf<<28) | 0x10<<20 | 0x8<<4
2822
2823 case ABL:
2824 return o&(0xf<<28) | 0x12fff3<<4
2825 }
2826
2827 c.ctxt.Diag("%v: bad rrr %d", p, a)
2828 return 0
2829 }
2830
2831 func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
2832 sc &= C_SCOND
2833 sc ^= C_SCOND_XOR
2834 if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
2835 return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
2836 }
2837 if sc != 0xe {
2838 c.ctxt.Diag("%v: .COND on bcond instruction", p)
2839 }
2840 switch a {
2841 case ABEQ:
2842 return 0x0<<28 | 0x5<<25
2843 case ABNE:
2844 return 0x1<<28 | 0x5<<25
2845 case ABCS:
2846 return 0x2<<28 | 0x5<<25
2847 case ABHS:
2848 return 0x2<<28 | 0x5<<25
2849 case ABCC:
2850 return 0x3<<28 | 0x5<<25
2851 case ABLO:
2852 return 0x3<<28 | 0x5<<25
2853 case ABMI:
2854 return 0x4<<28 | 0x5<<25
2855 case ABPL:
2856 return 0x5<<28 | 0x5<<25
2857 case ABVS:
2858 return 0x6<<28 | 0x5<<25
2859 case ABVC:
2860 return 0x7<<28 | 0x5<<25
2861 case ABHI:
2862 return 0x8<<28 | 0x5<<25
2863 case ABLS:
2864 return 0x9<<28 | 0x5<<25
2865 case ABGE:
2866 return 0xa<<28 | 0x5<<25
2867 case ABLT:
2868 return 0xb<<28 | 0x5<<25
2869 case ABGT:
2870 return 0xc<<28 | 0x5<<25
2871 case ABLE:
2872 return 0xd<<28 | 0x5<<25
2873 case AB:
2874 return 0xe<<28 | 0x5<<25
2875 }
2876
2877 c.ctxt.Diag("%v: bad bra %v", p, a)
2878 return 0
2879 }
2880
2881 func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
2882 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2883 if sc&C_PBIT == 0 {
2884 o |= 1 << 24
2885 }
2886 if sc&C_UBIT == 0 {
2887 o |= 1 << 23
2888 }
2889 if sc&C_WBIT != 0 {
2890 o |= 1 << 21
2891 }
2892 o |= 1<<26 | 1<<20
2893 if v < 0 {
2894 if sc&C_UBIT != 0 {
2895 c.ctxt.Diag(".U on neg offset")
2896 }
2897 v = -v
2898 o ^= 1 << 23
2899 }
2900
2901 if v >= 1<<12 || v < 0 {
2902 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2903 }
2904 o |= uint32(v)
2905 o |= (uint32(b) & 15) << 16
2906 o |= (uint32(r) & 15) << 12
2907 return o
2908 }
2909
2910 func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
2911 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2912 if sc&C_PBIT == 0 {
2913 o |= 1 << 24
2914 }
2915 if sc&C_WBIT != 0 {
2916 o |= 1 << 21
2917 }
2918 o |= 1<<23 | 1<<20 | 0xb<<4
2919 if v < 0 {
2920 v = -v
2921 o ^= 1 << 23
2922 }
2923
2924 if v >= 1<<8 || v < 0 {
2925 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
2926 }
2927 o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
2928 o |= (uint32(b) & 15) << 16
2929 o |= (uint32(r) & 15) << 12
2930 return o
2931 }
2932
2933 func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
2934 o := c.olr(v, b, r, sc) ^ (1 << 20)
2935 if a != AMOVW {
2936 o |= 1 << 22
2937 }
2938 return o
2939 }
2940
2941 func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
2942 o := c.olhr(v, b, r, sc) ^ (1 << 20)
2943 return o
2944 }
2945
2946 func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
2947 return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
2948 }
2949
2950 func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
2951 return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
2952 }
2953
2954 func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
2955 return c.olr(int32(i), b, r, sc) ^ (1 << 25)
2956 }
2957
2958 func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
2959 return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
2960 }
2961
2962 func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
2963 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
2964 if sc&C_PBIT == 0 {
2965 o |= 1 << 24
2966 }
2967 if sc&C_WBIT != 0 {
2968 o |= 1 << 21
2969 }
2970 o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
2971 if v < 0 {
2972 v = -v
2973 o ^= 1 << 23
2974 }
2975
2976 if v&3 != 0 {
2977 c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
2978 } else if v >= 1<<10 || v < 0 {
2979 c.ctxt.Diag("literal span too large: %d\n%v", v, p)
2980 }
2981 o |= (uint32(v) >> 2) & 0xFF
2982 o |= (uint32(b) & 15) << 16
2983 o |= (uint32(r) & 15) << 12
2984
2985 switch a {
2986 default:
2987 c.ctxt.Diag("bad fst %v", a)
2988 fallthrough
2989
2990 case AMOVD:
2991 o |= 1 << 8
2992 fallthrough
2993
2994 case AMOVF:
2995 break
2996 }
2997
2998 return o
2999 }
3000
3001
3002 func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3003 o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
3004 o1 |= 0x30 << 20
3005 o1 |= (uint32(dr) & 15) << 12
3006 o1 |= uint32(a.Offset) & 0x0fff
3007 o1 |= (uint32(a.Offset) & 0xf000) << 4
3008 return o1
3009 }
3010
3011
3012 func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3013 o1 := c.oprrr(p, AMOVW, int(p.Scond))
3014 o1 |= (uint32(dr) & 15) << 12
3015 v := immrot(^uint32(a.Offset))
3016 if v == 0 {
3017 c.ctxt.Diag("%v: missing literal", p)
3018 return 0
3019 }
3020 o1 |= uint32(v)
3021 return o1
3022 }
3023
3024 func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
3025 var o1 uint32
3026 if p.Pool == nil {
3027 c.aclass(a)
3028 v := immrot(^uint32(c.instoffset))
3029 if v == 0 {
3030 c.ctxt.Diag("%v: missing literal", p)
3031 return 0
3032 }
3033
3034 o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
3035 o1 |= uint32(v)
3036 o1 |= (uint32(dr) & 15) << 12
3037 } else {
3038 v := int32(p.Pool.Pc - p.Pc - 8)
3039 o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
3040 }
3041
3042 return o1
3043 }
3044
3045 func (c *ctxt5) chipzero5(e float64) int {
3046
3047 if objabi.GOARM < 7 || math.Float64bits(e) != 0 {
3048 return -1
3049 }
3050 return 0
3051 }
3052
3053 func (c *ctxt5) chipfloat5(e float64) int {
3054
3055 if objabi.GOARM < 7 {
3056 return -1
3057 }
3058
3059 ei := math.Float64bits(e)
3060 l := uint32(ei)
3061 h := uint32(ei >> 32)
3062
3063 if l != 0 || h&0xffff != 0 {
3064 return -1
3065 }
3066 h1 := h & 0x7fc00000
3067 if h1 != 0x40000000 && h1 != 0x3fc00000 {
3068 return -1
3069 }
3070 n := 0
3071
3072
3073 if h&0x80000000 != 0 {
3074 n |= 1 << 7
3075 }
3076
3077
3078 if h1 == 0x3fc00000 {
3079 n |= 1 << 6
3080 }
3081
3082
3083 n |= int((h >> 16) & 0x3f)
3084
3085
3086 return n
3087 }
3088
3089 func nocache(p *obj.Prog) {
3090 p.Optab = 0
3091 p.From.Class = 0
3092 if p.GetFrom3() != nil {
3093 p.GetFrom3().Class = 0
3094 }
3095 p.To.Class = 0
3096 }
3097
View as plain text