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