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