1
2
3
4
5 package arm
6
7 import (
8 "fmt"
9 "internal/buildcfg"
10 "math"
11 "math/bits"
12
13 "cmd/compile/internal/base"
14 "cmd/compile/internal/ir"
15 "cmd/compile/internal/logopt"
16 "cmd/compile/internal/ssa"
17 "cmd/compile/internal/ssagen"
18 "cmd/compile/internal/types"
19 "cmd/internal/obj"
20 "cmd/internal/obj/arm"
21 )
22
23
24 func loadByType(t *types.Type) obj.As {
25 if t.IsFloat() {
26 switch t.Size() {
27 case 4:
28 return arm.AMOVF
29 case 8:
30 return arm.AMOVD
31 }
32 } else {
33 switch t.Size() {
34 case 1:
35 if t.IsSigned() {
36 return arm.AMOVB
37 } else {
38 return arm.AMOVBU
39 }
40 case 2:
41 if t.IsSigned() {
42 return arm.AMOVH
43 } else {
44 return arm.AMOVHU
45 }
46 case 4:
47 return arm.AMOVW
48 }
49 }
50 panic("bad load type")
51 }
52
53
54 func storeByType(t *types.Type) obj.As {
55 if t.IsFloat() {
56 switch t.Size() {
57 case 4:
58 return arm.AMOVF
59 case 8:
60 return arm.AMOVD
61 }
62 } else {
63 switch t.Size() {
64 case 1:
65 return arm.AMOVB
66 case 2:
67 return arm.AMOVH
68 case 4:
69 return arm.AMOVW
70 }
71 }
72 panic("bad store type")
73 }
74
75
76 type shift int64
77
78
79 func (v shift) String() string {
80 op := "<<>>->@>"[((v>>5)&3)<<1:]
81 if v&(1<<4) != 0 {
82
83 return fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
84 } else {
85
86 return fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
87 }
88 }
89
90
91 func makeshift(reg int16, typ int64, s int64) shift {
92 return shift(int64(reg&0xf) | typ | (s&31)<<7)
93 }
94
95
96 func genshift(s *ssagen.State, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog {
97 p := s.Prog(as)
98 p.From.Type = obj.TYPE_SHIFT
99 p.From.Offset = int64(makeshift(r1, typ, n))
100 p.Reg = r0
101 if r != 0 {
102 p.To.Type = obj.TYPE_REG
103 p.To.Reg = r
104 }
105 return p
106 }
107
108
109 func makeregshift(r1 int16, typ int64, r2 int16) shift {
110 return shift(int64(r1&0xf) | typ | int64(r2&0xf)<<8 | 1<<4)
111 }
112
113
114 func genregshift(s *ssagen.State, as obj.As, r0, r1, r2, r int16, typ int64) *obj.Prog {
115 p := s.Prog(as)
116 p.From.Type = obj.TYPE_SHIFT
117 p.From.Offset = int64(makeregshift(r1, typ, r2))
118 p.Reg = r0
119 if r != 0 {
120 p.To.Type = obj.TYPE_REG
121 p.To.Reg = r
122 }
123 return p
124 }
125
126
127
128
129 func getBFC(v uint32) (uint32, uint32) {
130 var m, l uint32
131
132 if v == 0 {
133 return 0xffffffff, 0
134 }
135
136 l = uint32(bits.TrailingZeros32(v))
137
138 m = 32 - uint32(bits.LeadingZeros32(v))
139
140 if (1<<m)-(1<<l) == v {
141
142 return l, m - l
143 }
144
145 return 0xffffffff, 0
146 }
147
148 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
149 switch v.Op {
150 case ssa.OpCopy, ssa.OpARMMOVWreg:
151 if v.Type.IsMemory() {
152 return
153 }
154 x := v.Args[0].Reg()
155 y := v.Reg()
156 if x == y {
157 return
158 }
159 as := arm.AMOVW
160 if v.Type.IsFloat() {
161 switch v.Type.Size() {
162 case 4:
163 as = arm.AMOVF
164 case 8:
165 as = arm.AMOVD
166 default:
167 panic("bad float size")
168 }
169 }
170 p := s.Prog(as)
171 p.From.Type = obj.TYPE_REG
172 p.From.Reg = x
173 p.To.Type = obj.TYPE_REG
174 p.To.Reg = y
175 case ssa.OpARMMOVWnop:
176
177 case ssa.OpLoadReg:
178 if v.Type.IsFlags() {
179 v.Fatalf("load flags not implemented: %v", v.LongString())
180 return
181 }
182 p := s.Prog(loadByType(v.Type))
183 ssagen.AddrAuto(&p.From, v.Args[0])
184 p.To.Type = obj.TYPE_REG
185 p.To.Reg = v.Reg()
186 case ssa.OpStoreReg:
187 if v.Type.IsFlags() {
188 v.Fatalf("store flags not implemented: %v", v.LongString())
189 return
190 }
191 p := s.Prog(storeByType(v.Type))
192 p.From.Type = obj.TYPE_REG
193 p.From.Reg = v.Args[0].Reg()
194 ssagen.AddrAuto(&p.To, v)
195 case ssa.OpARMADD,
196 ssa.OpARMADC,
197 ssa.OpARMSUB,
198 ssa.OpARMSBC,
199 ssa.OpARMRSB,
200 ssa.OpARMAND,
201 ssa.OpARMOR,
202 ssa.OpARMXOR,
203 ssa.OpARMBIC,
204 ssa.OpARMMUL,
205 ssa.OpARMADDF,
206 ssa.OpARMADDD,
207 ssa.OpARMSUBF,
208 ssa.OpARMSUBD,
209 ssa.OpARMSLL,
210 ssa.OpARMSRL,
211 ssa.OpARMSRA,
212 ssa.OpARMMULF,
213 ssa.OpARMMULD,
214 ssa.OpARMNMULF,
215 ssa.OpARMNMULD,
216 ssa.OpARMDIVF,
217 ssa.OpARMDIVD:
218 r := v.Reg()
219 r1 := v.Args[0].Reg()
220 r2 := v.Args[1].Reg()
221 p := s.Prog(v.Op.Asm())
222 p.From.Type = obj.TYPE_REG
223 p.From.Reg = r2
224 p.Reg = r1
225 p.To.Type = obj.TYPE_REG
226 p.To.Reg = r
227 case ssa.OpARMSRR:
228 genregshift(s, arm.AMOVW, 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR)
229 case ssa.OpARMMULAF, ssa.OpARMMULAD, ssa.OpARMMULSF, ssa.OpARMMULSD, ssa.OpARMFMULAD:
230 r := v.Reg()
231 r0 := v.Args[0].Reg()
232 r1 := v.Args[1].Reg()
233 r2 := v.Args[2].Reg()
234 if r != r0 {
235 v.Fatalf("result and addend are not in the same register: %v", v.LongString())
236 }
237 p := s.Prog(v.Op.Asm())
238 p.From.Type = obj.TYPE_REG
239 p.From.Reg = r2
240 p.Reg = r1
241 p.To.Type = obj.TYPE_REG
242 p.To.Reg = r
243 case ssa.OpARMADDS,
244 ssa.OpARMSUBS:
245 r := v.Reg0()
246 r1 := v.Args[0].Reg()
247 r2 := v.Args[1].Reg()
248 p := s.Prog(v.Op.Asm())
249 p.Scond = arm.C_SBIT
250 p.From.Type = obj.TYPE_REG
251 p.From.Reg = r2
252 p.Reg = r1
253 p.To.Type = obj.TYPE_REG
254 p.To.Reg = r
255 case ssa.OpARMSRAcond:
256
257
258
259
260
261 r := v.Reg()
262 r1 := v.Args[0].Reg()
263 r2 := v.Args[1].Reg()
264 p := s.Prog(arm.ASRA)
265 p.Scond = arm.C_SCOND_HS
266 p.From.Type = obj.TYPE_CONST
267 p.From.Offset = 31
268 p.Reg = r1
269 p.To.Type = obj.TYPE_REG
270 p.To.Reg = r
271 p = s.Prog(arm.ASRA)
272 p.Scond = arm.C_SCOND_LO
273 p.From.Type = obj.TYPE_REG
274 p.From.Reg = r2
275 p.Reg = r1
276 p.To.Type = obj.TYPE_REG
277 p.To.Reg = r
278 case ssa.OpARMBFX, ssa.OpARMBFXU:
279 p := s.Prog(v.Op.Asm())
280 p.From.Type = obj.TYPE_CONST
281 p.From.Offset = v.AuxInt >> 8
282 p.SetFrom3Const(v.AuxInt & 0xff)
283 p.Reg = v.Args[0].Reg()
284 p.To.Type = obj.TYPE_REG
285 p.To.Reg = v.Reg()
286 case ssa.OpARMANDconst, ssa.OpARMBICconst:
287
288
289 if buildcfg.GOARM == 7 && v.Reg() == v.Args[0].Reg() {
290 var val uint32
291 if v.Op == ssa.OpARMANDconst {
292 val = ^uint32(v.AuxInt)
293 } else {
294 val = uint32(v.AuxInt)
295 }
296 lsb, width := getBFC(val)
297
298 if 8 < width && width < 24 {
299 p := s.Prog(arm.ABFC)
300 p.From.Type = obj.TYPE_CONST
301 p.From.Offset = int64(width)
302 p.SetFrom3Const(int64(lsb))
303 p.To.Type = obj.TYPE_REG
304 p.To.Reg = v.Reg()
305 break
306 }
307 }
308
309 fallthrough
310 case ssa.OpARMADDconst,
311 ssa.OpARMADCconst,
312 ssa.OpARMSUBconst,
313 ssa.OpARMSBCconst,
314 ssa.OpARMRSBconst,
315 ssa.OpARMRSCconst,
316 ssa.OpARMORconst,
317 ssa.OpARMXORconst,
318 ssa.OpARMSLLconst,
319 ssa.OpARMSRLconst,
320 ssa.OpARMSRAconst:
321 p := s.Prog(v.Op.Asm())
322 p.From.Type = obj.TYPE_CONST
323 p.From.Offset = v.AuxInt
324 p.Reg = v.Args[0].Reg()
325 p.To.Type = obj.TYPE_REG
326 p.To.Reg = v.Reg()
327 case ssa.OpARMADDSconst,
328 ssa.OpARMSUBSconst,
329 ssa.OpARMRSBSconst:
330 p := s.Prog(v.Op.Asm())
331 p.Scond = arm.C_SBIT
332 p.From.Type = obj.TYPE_CONST
333 p.From.Offset = v.AuxInt
334 p.Reg = v.Args[0].Reg()
335 p.To.Type = obj.TYPE_REG
336 p.To.Reg = v.Reg0()
337 case ssa.OpARMSRRconst:
338 genshift(s, arm.AMOVW, 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt)
339 case ssa.OpARMADDshiftLL,
340 ssa.OpARMADCshiftLL,
341 ssa.OpARMSUBshiftLL,
342 ssa.OpARMSBCshiftLL,
343 ssa.OpARMRSBshiftLL,
344 ssa.OpARMRSCshiftLL,
345 ssa.OpARMANDshiftLL,
346 ssa.OpARMORshiftLL,
347 ssa.OpARMXORshiftLL,
348 ssa.OpARMBICshiftLL:
349 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
350 case ssa.OpARMADDSshiftLL,
351 ssa.OpARMSUBSshiftLL,
352 ssa.OpARMRSBSshiftLL:
353 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LL, v.AuxInt)
354 p.Scond = arm.C_SBIT
355 case ssa.OpARMADDshiftRL,
356 ssa.OpARMADCshiftRL,
357 ssa.OpARMSUBshiftRL,
358 ssa.OpARMSBCshiftRL,
359 ssa.OpARMRSBshiftRL,
360 ssa.OpARMRSCshiftRL,
361 ssa.OpARMANDshiftRL,
362 ssa.OpARMORshiftRL,
363 ssa.OpARMXORshiftRL,
364 ssa.OpARMBICshiftRL:
365 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
366 case ssa.OpARMADDSshiftRL,
367 ssa.OpARMSUBSshiftRL,
368 ssa.OpARMRSBSshiftRL:
369 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LR, v.AuxInt)
370 p.Scond = arm.C_SBIT
371 case ssa.OpARMADDshiftRA,
372 ssa.OpARMADCshiftRA,
373 ssa.OpARMSUBshiftRA,
374 ssa.OpARMSBCshiftRA,
375 ssa.OpARMRSBshiftRA,
376 ssa.OpARMRSCshiftRA,
377 ssa.OpARMANDshiftRA,
378 ssa.OpARMORshiftRA,
379 ssa.OpARMXORshiftRA,
380 ssa.OpARMBICshiftRA:
381 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
382 case ssa.OpARMADDSshiftRA,
383 ssa.OpARMSUBSshiftRA,
384 ssa.OpARMRSBSshiftRA:
385 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_AR, v.AuxInt)
386 p.Scond = arm.C_SBIT
387 case ssa.OpARMXORshiftRR:
388 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt)
389 case ssa.OpARMMVNshiftLL:
390 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
391 case ssa.OpARMMVNshiftRL:
392 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
393 case ssa.OpARMMVNshiftRA:
394 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
395 case ssa.OpARMMVNshiftLLreg:
396 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL)
397 case ssa.OpARMMVNshiftRLreg:
398 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR)
399 case ssa.OpARMMVNshiftRAreg:
400 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR)
401 case ssa.OpARMADDshiftLLreg,
402 ssa.OpARMADCshiftLLreg,
403 ssa.OpARMSUBshiftLLreg,
404 ssa.OpARMSBCshiftLLreg,
405 ssa.OpARMRSBshiftLLreg,
406 ssa.OpARMRSCshiftLLreg,
407 ssa.OpARMANDshiftLLreg,
408 ssa.OpARMORshiftLLreg,
409 ssa.OpARMXORshiftLLreg,
410 ssa.OpARMBICshiftLLreg:
411 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_LL)
412 case ssa.OpARMADDSshiftLLreg,
413 ssa.OpARMSUBSshiftLLreg,
414 ssa.OpARMRSBSshiftLLreg:
415 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_LL)
416 p.Scond = arm.C_SBIT
417 case ssa.OpARMADDshiftRLreg,
418 ssa.OpARMADCshiftRLreg,
419 ssa.OpARMSUBshiftRLreg,
420 ssa.OpARMSBCshiftRLreg,
421 ssa.OpARMRSBshiftRLreg,
422 ssa.OpARMRSCshiftRLreg,
423 ssa.OpARMANDshiftRLreg,
424 ssa.OpARMORshiftRLreg,
425 ssa.OpARMXORshiftRLreg,
426 ssa.OpARMBICshiftRLreg:
427 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_LR)
428 case ssa.OpARMADDSshiftRLreg,
429 ssa.OpARMSUBSshiftRLreg,
430 ssa.OpARMRSBSshiftRLreg:
431 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_LR)
432 p.Scond = arm.C_SBIT
433 case ssa.OpARMADDshiftRAreg,
434 ssa.OpARMADCshiftRAreg,
435 ssa.OpARMSUBshiftRAreg,
436 ssa.OpARMSBCshiftRAreg,
437 ssa.OpARMRSBshiftRAreg,
438 ssa.OpARMRSCshiftRAreg,
439 ssa.OpARMANDshiftRAreg,
440 ssa.OpARMORshiftRAreg,
441 ssa.OpARMXORshiftRAreg,
442 ssa.OpARMBICshiftRAreg:
443 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_AR)
444 case ssa.OpARMADDSshiftRAreg,
445 ssa.OpARMSUBSshiftRAreg,
446 ssa.OpARMRSBSshiftRAreg:
447 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_AR)
448 p.Scond = arm.C_SBIT
449 case ssa.OpARMHMUL,
450 ssa.OpARMHMULU:
451
452 p := s.Prog(v.Op.Asm())
453 p.From.Type = obj.TYPE_REG
454 p.From.Reg = v.Args[0].Reg()
455 p.Reg = v.Args[1].Reg()
456 p.To.Type = obj.TYPE_REGREG
457 p.To.Reg = v.Reg()
458 p.To.Offset = arm.REGTMP
459 case ssa.OpARMMULLU:
460
461 p := s.Prog(v.Op.Asm())
462 p.From.Type = obj.TYPE_REG
463 p.From.Reg = v.Args[0].Reg()
464 p.Reg = v.Args[1].Reg()
465 p.To.Type = obj.TYPE_REGREG
466 p.To.Reg = v.Reg0()
467 p.To.Offset = int64(v.Reg1())
468 case ssa.OpARMMULA, ssa.OpARMMULS:
469 p := s.Prog(v.Op.Asm())
470 p.From.Type = obj.TYPE_REG
471 p.From.Reg = v.Args[0].Reg()
472 p.Reg = v.Args[1].Reg()
473 p.To.Type = obj.TYPE_REGREG2
474 p.To.Reg = v.Reg()
475 p.To.Offset = int64(v.Args[2].Reg())
476 case ssa.OpARMMOVWconst:
477 p := s.Prog(v.Op.Asm())
478 p.From.Type = obj.TYPE_CONST
479 p.From.Offset = v.AuxInt
480 p.To.Type = obj.TYPE_REG
481 p.To.Reg = v.Reg()
482 case ssa.OpARMMOVFconst,
483 ssa.OpARMMOVDconst:
484 p := s.Prog(v.Op.Asm())
485 p.From.Type = obj.TYPE_FCONST
486 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
487 p.To.Type = obj.TYPE_REG
488 p.To.Reg = v.Reg()
489 case ssa.OpARMCMP,
490 ssa.OpARMCMN,
491 ssa.OpARMTST,
492 ssa.OpARMTEQ,
493 ssa.OpARMCMPF,
494 ssa.OpARMCMPD:
495 p := s.Prog(v.Op.Asm())
496 p.From.Type = obj.TYPE_REG
497
498
499 p.From.Reg = v.Args[1].Reg()
500 p.Reg = v.Args[0].Reg()
501 case ssa.OpARMCMPconst,
502 ssa.OpARMCMNconst,
503 ssa.OpARMTSTconst,
504 ssa.OpARMTEQconst:
505
506 p := s.Prog(v.Op.Asm())
507 p.From.Type = obj.TYPE_CONST
508 p.From.Offset = v.AuxInt
509 p.Reg = v.Args[0].Reg()
510 case ssa.OpARMCMPF0,
511 ssa.OpARMCMPD0:
512 p := s.Prog(v.Op.Asm())
513 p.From.Type = obj.TYPE_REG
514 p.From.Reg = v.Args[0].Reg()
515 case ssa.OpARMCMPshiftLL, ssa.OpARMCMNshiftLL, ssa.OpARMTSTshiftLL, ssa.OpARMTEQshiftLL:
516 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LL, v.AuxInt)
517 case ssa.OpARMCMPshiftRL, ssa.OpARMCMNshiftRL, ssa.OpARMTSTshiftRL, ssa.OpARMTEQshiftRL:
518 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LR, v.AuxInt)
519 case ssa.OpARMCMPshiftRA, ssa.OpARMCMNshiftRA, ssa.OpARMTSTshiftRA, ssa.OpARMTEQshiftRA:
520 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_AR, v.AuxInt)
521 case ssa.OpARMCMPshiftLLreg, ssa.OpARMCMNshiftLLreg, ssa.OpARMTSTshiftLLreg, ssa.OpARMTEQshiftLLreg:
522 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_LL)
523 case ssa.OpARMCMPshiftRLreg, ssa.OpARMCMNshiftRLreg, ssa.OpARMTSTshiftRLreg, ssa.OpARMTEQshiftRLreg:
524 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_LR)
525 case ssa.OpARMCMPshiftRAreg, ssa.OpARMCMNshiftRAreg, ssa.OpARMTSTshiftRAreg, ssa.OpARMTEQshiftRAreg:
526 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_AR)
527 case ssa.OpARMMOVWaddr:
528 p := s.Prog(arm.AMOVW)
529 p.From.Type = obj.TYPE_ADDR
530 p.From.Reg = v.Args[0].Reg()
531 p.To.Type = obj.TYPE_REG
532 p.To.Reg = v.Reg()
533
534 var wantreg string
535
536
537
538
539
540 switch v.Aux.(type) {
541 default:
542 v.Fatalf("aux is of unknown type %T", v.Aux)
543 case *obj.LSym:
544 wantreg = "SB"
545 ssagen.AddAux(&p.From, v)
546 case *ir.Name:
547 wantreg = "SP"
548 ssagen.AddAux(&p.From, v)
549 case nil:
550
551 wantreg = "SP"
552 p.From.Offset = v.AuxInt
553 }
554 if reg := v.Args[0].RegName(); reg != wantreg {
555 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
556 }
557
558 case ssa.OpARMMOVBload,
559 ssa.OpARMMOVBUload,
560 ssa.OpARMMOVHload,
561 ssa.OpARMMOVHUload,
562 ssa.OpARMMOVWload,
563 ssa.OpARMMOVFload,
564 ssa.OpARMMOVDload:
565 p := s.Prog(v.Op.Asm())
566 p.From.Type = obj.TYPE_MEM
567 p.From.Reg = v.Args[0].Reg()
568 ssagen.AddAux(&p.From, v)
569 p.To.Type = obj.TYPE_REG
570 p.To.Reg = v.Reg()
571 case ssa.OpARMMOVBstore,
572 ssa.OpARMMOVHstore,
573 ssa.OpARMMOVWstore,
574 ssa.OpARMMOVFstore,
575 ssa.OpARMMOVDstore:
576 p := s.Prog(v.Op.Asm())
577 p.From.Type = obj.TYPE_REG
578 p.From.Reg = v.Args[1].Reg()
579 p.To.Type = obj.TYPE_MEM
580 p.To.Reg = v.Args[0].Reg()
581 ssagen.AddAux(&p.To, v)
582 case ssa.OpARMMOVWloadidx, ssa.OpARMMOVBUloadidx, ssa.OpARMMOVBloadidx, ssa.OpARMMOVHUloadidx, ssa.OpARMMOVHloadidx:
583
584 fallthrough
585 case ssa.OpARMMOVWloadshiftLL:
586 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
587 p.From.Reg = v.Args[0].Reg()
588 case ssa.OpARMMOVWloadshiftRL:
589 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
590 p.From.Reg = v.Args[0].Reg()
591 case ssa.OpARMMOVWloadshiftRA:
592 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
593 p.From.Reg = v.Args[0].Reg()
594 case ssa.OpARMMOVWstoreidx, ssa.OpARMMOVBstoreidx, ssa.OpARMMOVHstoreidx:
595
596 fallthrough
597 case ssa.OpARMMOVWstoreshiftLL:
598 p := s.Prog(v.Op.Asm())
599 p.From.Type = obj.TYPE_REG
600 p.From.Reg = v.Args[2].Reg()
601 p.To.Type = obj.TYPE_SHIFT
602 p.To.Reg = v.Args[0].Reg()
603 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LL, v.AuxInt))
604 case ssa.OpARMMOVWstoreshiftRL:
605 p := s.Prog(v.Op.Asm())
606 p.From.Type = obj.TYPE_REG
607 p.From.Reg = v.Args[2].Reg()
608 p.To.Type = obj.TYPE_SHIFT
609 p.To.Reg = v.Args[0].Reg()
610 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LR, v.AuxInt))
611 case ssa.OpARMMOVWstoreshiftRA:
612 p := s.Prog(v.Op.Asm())
613 p.From.Type = obj.TYPE_REG
614 p.From.Reg = v.Args[2].Reg()
615 p.To.Type = obj.TYPE_SHIFT
616 p.To.Reg = v.Args[0].Reg()
617 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_AR, v.AuxInt))
618 case ssa.OpARMMOVBreg,
619 ssa.OpARMMOVBUreg,
620 ssa.OpARMMOVHreg,
621 ssa.OpARMMOVHUreg:
622 a := v.Args[0]
623 for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg || a.Op == ssa.OpARMMOVWnop {
624 a = a.Args[0]
625 }
626 if a.Op == ssa.OpLoadReg {
627 t := a.Type
628 switch {
629 case v.Op == ssa.OpARMMOVBreg && t.Size() == 1 && t.IsSigned(),
630 v.Op == ssa.OpARMMOVBUreg && t.Size() == 1 && !t.IsSigned(),
631 v.Op == ssa.OpARMMOVHreg && t.Size() == 2 && t.IsSigned(),
632 v.Op == ssa.OpARMMOVHUreg && t.Size() == 2 && !t.IsSigned():
633
634 if v.Reg() == v.Args[0].Reg() {
635 return
636 }
637 p := s.Prog(arm.AMOVW)
638 p.From.Type = obj.TYPE_REG
639 p.From.Reg = v.Args[0].Reg()
640 p.To.Type = obj.TYPE_REG
641 p.To.Reg = v.Reg()
642 return
643 default:
644 }
645 }
646 if buildcfg.GOARM >= 6 {
647
648 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0)
649 return
650 }
651 fallthrough
652 case ssa.OpARMMVN,
653 ssa.OpARMCLZ,
654 ssa.OpARMREV,
655 ssa.OpARMREV16,
656 ssa.OpARMRBIT,
657 ssa.OpARMSQRTF,
658 ssa.OpARMSQRTD,
659 ssa.OpARMNEGF,
660 ssa.OpARMNEGD,
661 ssa.OpARMABSD,
662 ssa.OpARMMOVWF,
663 ssa.OpARMMOVWD,
664 ssa.OpARMMOVFW,
665 ssa.OpARMMOVDW,
666 ssa.OpARMMOVFD,
667 ssa.OpARMMOVDF:
668 p := s.Prog(v.Op.Asm())
669 p.From.Type = obj.TYPE_REG
670 p.From.Reg = v.Args[0].Reg()
671 p.To.Type = obj.TYPE_REG
672 p.To.Reg = v.Reg()
673 case ssa.OpARMMOVWUF,
674 ssa.OpARMMOVWUD,
675 ssa.OpARMMOVFWU,
676 ssa.OpARMMOVDWU:
677 p := s.Prog(v.Op.Asm())
678 p.Scond = arm.C_UBIT
679 p.From.Type = obj.TYPE_REG
680 p.From.Reg = v.Args[0].Reg()
681 p.To.Type = obj.TYPE_REG
682 p.To.Reg = v.Reg()
683 case ssa.OpARMCMOVWHSconst:
684 p := s.Prog(arm.AMOVW)
685 p.Scond = arm.C_SCOND_HS
686 p.From.Type = obj.TYPE_CONST
687 p.From.Offset = v.AuxInt
688 p.To.Type = obj.TYPE_REG
689 p.To.Reg = v.Reg()
690 case ssa.OpARMCMOVWLSconst:
691 p := s.Prog(arm.AMOVW)
692 p.Scond = arm.C_SCOND_LS
693 p.From.Type = obj.TYPE_CONST
694 p.From.Offset = v.AuxInt
695 p.To.Type = obj.TYPE_REG
696 p.To.Reg = v.Reg()
697 case ssa.OpARMCALLstatic, ssa.OpARMCALLclosure, ssa.OpARMCALLinter:
698 s.Call(v)
699 case ssa.OpARMCALLudiv:
700 p := s.Prog(obj.ACALL)
701 p.To.Type = obj.TYPE_MEM
702 p.To.Name = obj.NAME_EXTERN
703 p.To.Sym = ir.Syms.Udiv
704 case ssa.OpARMLoweredWB:
705 p := s.Prog(obj.ACALL)
706 p.To.Type = obj.TYPE_MEM
707 p.To.Name = obj.NAME_EXTERN
708 p.To.Sym = v.Aux.(*obj.LSym)
709 case ssa.OpARMLoweredPanicBoundsA, ssa.OpARMLoweredPanicBoundsB, ssa.OpARMLoweredPanicBoundsC:
710 p := s.Prog(obj.ACALL)
711 p.To.Type = obj.TYPE_MEM
712 p.To.Name = obj.NAME_EXTERN
713 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
714 s.UseArgs(8)
715 case ssa.OpARMLoweredPanicExtendA, ssa.OpARMLoweredPanicExtendB, ssa.OpARMLoweredPanicExtendC:
716 p := s.Prog(obj.ACALL)
717 p.To.Type = obj.TYPE_MEM
718 p.To.Name = obj.NAME_EXTERN
719 p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
720 s.UseArgs(12)
721 case ssa.OpARMDUFFZERO:
722 p := s.Prog(obj.ADUFFZERO)
723 p.To.Type = obj.TYPE_MEM
724 p.To.Name = obj.NAME_EXTERN
725 p.To.Sym = ir.Syms.Duffzero
726 p.To.Offset = v.AuxInt
727 case ssa.OpARMDUFFCOPY:
728 p := s.Prog(obj.ADUFFCOPY)
729 p.To.Type = obj.TYPE_MEM
730 p.To.Name = obj.NAME_EXTERN
731 p.To.Sym = ir.Syms.Duffcopy
732 p.To.Offset = v.AuxInt
733 case ssa.OpARMLoweredNilCheck:
734
735 p := s.Prog(arm.AMOVB)
736 p.From.Type = obj.TYPE_MEM
737 p.From.Reg = v.Args[0].Reg()
738 ssagen.AddAux(&p.From, v)
739 p.To.Type = obj.TYPE_REG
740 p.To.Reg = arm.REGTMP
741 if logopt.Enabled() {
742 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
743 }
744 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
745 base.WarnfAt(v.Pos, "generated nil check")
746 }
747 case ssa.OpARMLoweredZero:
748
749
750
751
752
753
754 var sz int64
755 var mov obj.As
756 switch {
757 case v.AuxInt%4 == 0:
758 sz = 4
759 mov = arm.AMOVW
760 case v.AuxInt%2 == 0:
761 sz = 2
762 mov = arm.AMOVH
763 default:
764 sz = 1
765 mov = arm.AMOVB
766 }
767 p := s.Prog(mov)
768 p.Scond = arm.C_PBIT
769 p.From.Type = obj.TYPE_REG
770 p.From.Reg = v.Args[2].Reg()
771 p.To.Type = obj.TYPE_MEM
772 p.To.Reg = arm.REG_R1
773 p.To.Offset = sz
774 p2 := s.Prog(arm.ACMP)
775 p2.From.Type = obj.TYPE_REG
776 p2.From.Reg = v.Args[1].Reg()
777 p2.Reg = arm.REG_R1
778 p3 := s.Prog(arm.ABLE)
779 p3.To.Type = obj.TYPE_BRANCH
780 p3.To.SetTarget(p)
781 case ssa.OpARMLoweredMove:
782
783
784
785
786
787
788 var sz int64
789 var mov obj.As
790 switch {
791 case v.AuxInt%4 == 0:
792 sz = 4
793 mov = arm.AMOVW
794 case v.AuxInt%2 == 0:
795 sz = 2
796 mov = arm.AMOVH
797 default:
798 sz = 1
799 mov = arm.AMOVB
800 }
801 p := s.Prog(mov)
802 p.Scond = arm.C_PBIT
803 p.From.Type = obj.TYPE_MEM
804 p.From.Reg = arm.REG_R1
805 p.From.Offset = sz
806 p.To.Type = obj.TYPE_REG
807 p.To.Reg = arm.REGTMP
808 p2 := s.Prog(mov)
809 p2.Scond = arm.C_PBIT
810 p2.From.Type = obj.TYPE_REG
811 p2.From.Reg = arm.REGTMP
812 p2.To.Type = obj.TYPE_MEM
813 p2.To.Reg = arm.REG_R2
814 p2.To.Offset = sz
815 p3 := s.Prog(arm.ACMP)
816 p3.From.Type = obj.TYPE_REG
817 p3.From.Reg = v.Args[2].Reg()
818 p3.Reg = arm.REG_R1
819 p4 := s.Prog(arm.ABLE)
820 p4.To.Type = obj.TYPE_BRANCH
821 p4.To.SetTarget(p)
822 case ssa.OpARMEqual,
823 ssa.OpARMNotEqual,
824 ssa.OpARMLessThan,
825 ssa.OpARMLessEqual,
826 ssa.OpARMGreaterThan,
827 ssa.OpARMGreaterEqual,
828 ssa.OpARMLessThanU,
829 ssa.OpARMLessEqualU,
830 ssa.OpARMGreaterThanU,
831 ssa.OpARMGreaterEqualU:
832
833
834 p := s.Prog(arm.AMOVW)
835 p.From.Type = obj.TYPE_CONST
836 p.From.Offset = 0
837 p.To.Type = obj.TYPE_REG
838 p.To.Reg = v.Reg()
839 p = s.Prog(arm.AMOVW)
840 p.Scond = condBits[v.Op]
841 p.From.Type = obj.TYPE_CONST
842 p.From.Offset = 1
843 p.To.Type = obj.TYPE_REG
844 p.To.Reg = v.Reg()
845 case ssa.OpARMLoweredGetClosurePtr:
846
847 ssagen.CheckLoweredGetClosurePtr(v)
848 case ssa.OpARMLoweredGetCallerSP:
849
850 p := s.Prog(arm.AMOVW)
851 p.From.Type = obj.TYPE_ADDR
852 p.From.Offset = -base.Ctxt.FixedFrameSize()
853 p.From.Name = obj.NAME_PARAM
854 p.To.Type = obj.TYPE_REG
855 p.To.Reg = v.Reg()
856 case ssa.OpARMLoweredGetCallerPC:
857 p := s.Prog(obj.AGETCALLERPC)
858 p.To.Type = obj.TYPE_REG
859 p.To.Reg = v.Reg()
860 case ssa.OpARMFlagConstant:
861 v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString())
862 case ssa.OpARMInvertFlags:
863 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
864 case ssa.OpClobber, ssa.OpClobberReg:
865
866 default:
867 v.Fatalf("genValue not implemented: %s", v.LongString())
868 }
869 }
870
871 var condBits = map[ssa.Op]uint8{
872 ssa.OpARMEqual: arm.C_SCOND_EQ,
873 ssa.OpARMNotEqual: arm.C_SCOND_NE,
874 ssa.OpARMLessThan: arm.C_SCOND_LT,
875 ssa.OpARMLessThanU: arm.C_SCOND_LO,
876 ssa.OpARMLessEqual: arm.C_SCOND_LE,
877 ssa.OpARMLessEqualU: arm.C_SCOND_LS,
878 ssa.OpARMGreaterThan: arm.C_SCOND_GT,
879 ssa.OpARMGreaterThanU: arm.C_SCOND_HI,
880 ssa.OpARMGreaterEqual: arm.C_SCOND_GE,
881 ssa.OpARMGreaterEqualU: arm.C_SCOND_HS,
882 }
883
884 var blockJump = map[ssa.BlockKind]struct {
885 asm, invasm obj.As
886 }{
887 ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE},
888 ssa.BlockARMNE: {arm.ABNE, arm.ABEQ},
889 ssa.BlockARMLT: {arm.ABLT, arm.ABGE},
890 ssa.BlockARMGE: {arm.ABGE, arm.ABLT},
891 ssa.BlockARMLE: {arm.ABLE, arm.ABGT},
892 ssa.BlockARMGT: {arm.ABGT, arm.ABLE},
893 ssa.BlockARMULT: {arm.ABLO, arm.ABHS},
894 ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
895 ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
896 ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
897 ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL},
898 ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI},
899 }
900
901
902 var leJumps = [2][2]ssagen.IndexJump{
903 {{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}},
904 {{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}},
905 }
906
907
908 var gtJumps = [2][2]ssagen.IndexJump{
909 {{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}},
910 {{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}},
911 }
912
913 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
914 switch b.Kind {
915 case ssa.BlockPlain:
916 if b.Succs[0].Block() != next {
917 p := s.Prog(obj.AJMP)
918 p.To.Type = obj.TYPE_BRANCH
919 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
920 }
921
922 case ssa.BlockDefer:
923
924
925
926 p := s.Prog(arm.ACMP)
927 p.From.Type = obj.TYPE_CONST
928 p.From.Offset = 0
929 p.Reg = arm.REG_R0
930 p = s.Prog(arm.ABNE)
931 p.To.Type = obj.TYPE_BRANCH
932 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
933 if b.Succs[0].Block() != next {
934 p := s.Prog(obj.AJMP)
935 p.To.Type = obj.TYPE_BRANCH
936 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
937 }
938
939 case ssa.BlockExit:
940
941 case ssa.BlockRet:
942 s.Prog(obj.ARET)
943
944 case ssa.BlockRetJmp:
945 p := s.Prog(obj.ARET)
946 p.To.Type = obj.TYPE_MEM
947 p.To.Name = obj.NAME_EXTERN
948 p.To.Sym = b.Aux.(*obj.LSym)
949
950 case ssa.BlockARMEQ, ssa.BlockARMNE,
951 ssa.BlockARMLT, ssa.BlockARMGE,
952 ssa.BlockARMLE, ssa.BlockARMGT,
953 ssa.BlockARMULT, ssa.BlockARMUGT,
954 ssa.BlockARMULE, ssa.BlockARMUGE,
955 ssa.BlockARMLTnoov, ssa.BlockARMGEnoov:
956 jmp := blockJump[b.Kind]
957 switch next {
958 case b.Succs[0].Block():
959 s.Br(jmp.invasm, b.Succs[1].Block())
960 case b.Succs[1].Block():
961 s.Br(jmp.asm, b.Succs[0].Block())
962 default:
963 if b.Likely != ssa.BranchUnlikely {
964 s.Br(jmp.asm, b.Succs[0].Block())
965 s.Br(obj.AJMP, b.Succs[1].Block())
966 } else {
967 s.Br(jmp.invasm, b.Succs[1].Block())
968 s.Br(obj.AJMP, b.Succs[0].Block())
969 }
970 }
971
972 case ssa.BlockARMLEnoov:
973 s.CombJump(b, next, &leJumps)
974
975 case ssa.BlockARMGTnoov:
976 s.CombJump(b, next, >Jumps)
977
978 default:
979 b.Fatalf("branch not implemented: %s", b.LongString())
980 }
981 }
982
View as plain text