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.SetFrom3Const(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 == 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.SetFrom3Const(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 >= 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 p.To.Sym = v.Aux.(*obj.LSym)
714 case ssa.OpARMLoweredPanicBoundsA, ssa.OpARMLoweredPanicBoundsB, ssa.OpARMLoweredPanicBoundsC:
715 p := s.Prog(obj.ACALL)
716 p.To.Type = obj.TYPE_MEM
717 p.To.Name = obj.NAME_EXTERN
718 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
719 s.UseArgs(8)
720 case ssa.OpARMLoweredPanicExtendA, ssa.OpARMLoweredPanicExtendB, ssa.OpARMLoweredPanicExtendC:
721 p := s.Prog(obj.ACALL)
722 p.To.Type = obj.TYPE_MEM
723 p.To.Name = obj.NAME_EXTERN
724 p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
725 s.UseArgs(12)
726 case ssa.OpARMDUFFZERO:
727 p := s.Prog(obj.ADUFFZERO)
728 p.To.Type = obj.TYPE_MEM
729 p.To.Name = obj.NAME_EXTERN
730 p.To.Sym = ir.Syms.Duffzero
731 p.To.Offset = v.AuxInt
732 case ssa.OpARMDUFFCOPY:
733 p := s.Prog(obj.ADUFFCOPY)
734 p.To.Type = obj.TYPE_MEM
735 p.To.Name = obj.NAME_EXTERN
736 p.To.Sym = ir.Syms.Duffcopy
737 p.To.Offset = v.AuxInt
738 case ssa.OpARMLoweredNilCheck:
739
740 p := s.Prog(arm.AMOVB)
741 p.From.Type = obj.TYPE_MEM
742 p.From.Reg = v.Args[0].Reg()
743 ssagen.AddAux(&p.From, v)
744 p.To.Type = obj.TYPE_REG
745 p.To.Reg = arm.REGTMP
746 if logopt.Enabled() {
747 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
748 }
749 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
750 base.WarnfAt(v.Pos, "generated nil check")
751 }
752 case ssa.OpARMLoweredZero:
753
754
755
756
757
758
759 var sz int64
760 var mov obj.As
761 switch {
762 case v.AuxInt%4 == 0:
763 sz = 4
764 mov = arm.AMOVW
765 case v.AuxInt%2 == 0:
766 sz = 2
767 mov = arm.AMOVH
768 default:
769 sz = 1
770 mov = arm.AMOVB
771 }
772 p := s.Prog(mov)
773 p.Scond = arm.C_PBIT
774 p.From.Type = obj.TYPE_REG
775 p.From.Reg = v.Args[2].Reg()
776 p.To.Type = obj.TYPE_MEM
777 p.To.Reg = arm.REG_R1
778 p.To.Offset = sz
779 p2 := s.Prog(arm.ACMP)
780 p2.From.Type = obj.TYPE_REG
781 p2.From.Reg = v.Args[1].Reg()
782 p2.Reg = arm.REG_R1
783 p3 := s.Prog(arm.ABLE)
784 p3.To.Type = obj.TYPE_BRANCH
785 p3.To.SetTarget(p)
786 case ssa.OpARMLoweredMove:
787
788
789
790
791
792
793 var sz int64
794 var mov obj.As
795 switch {
796 case v.AuxInt%4 == 0:
797 sz = 4
798 mov = arm.AMOVW
799 case v.AuxInt%2 == 0:
800 sz = 2
801 mov = arm.AMOVH
802 default:
803 sz = 1
804 mov = arm.AMOVB
805 }
806 p := s.Prog(mov)
807 p.Scond = arm.C_PBIT
808 p.From.Type = obj.TYPE_MEM
809 p.From.Reg = arm.REG_R1
810 p.From.Offset = sz
811 p.To.Type = obj.TYPE_REG
812 p.To.Reg = arm.REGTMP
813 p2 := s.Prog(mov)
814 p2.Scond = arm.C_PBIT
815 p2.From.Type = obj.TYPE_REG
816 p2.From.Reg = arm.REGTMP
817 p2.To.Type = obj.TYPE_MEM
818 p2.To.Reg = arm.REG_R2
819 p2.To.Offset = sz
820 p3 := s.Prog(arm.ACMP)
821 p3.From.Type = obj.TYPE_REG
822 p3.From.Reg = v.Args[2].Reg()
823 p3.Reg = arm.REG_R1
824 p4 := s.Prog(arm.ABLE)
825 p4.To.Type = obj.TYPE_BRANCH
826 p4.To.SetTarget(p)
827 case ssa.OpARMEqual,
828 ssa.OpARMNotEqual,
829 ssa.OpARMLessThan,
830 ssa.OpARMLessEqual,
831 ssa.OpARMGreaterThan,
832 ssa.OpARMGreaterEqual,
833 ssa.OpARMLessThanU,
834 ssa.OpARMLessEqualU,
835 ssa.OpARMGreaterThanU,
836 ssa.OpARMGreaterEqualU:
837
838
839 p := s.Prog(arm.AMOVW)
840 p.From.Type = obj.TYPE_CONST
841 p.From.Offset = 0
842 p.To.Type = obj.TYPE_REG
843 p.To.Reg = v.Reg()
844 p = s.Prog(arm.AMOVW)
845 p.Scond = condBits[v.Op]
846 p.From.Type = obj.TYPE_CONST
847 p.From.Offset = 1
848 p.To.Type = obj.TYPE_REG
849 p.To.Reg = v.Reg()
850 case ssa.OpARMLoweredGetClosurePtr:
851
852 ssagen.CheckLoweredGetClosurePtr(v)
853 case ssa.OpARMLoweredGetCallerSP:
854
855 p := s.Prog(arm.AMOVW)
856 p.From.Type = obj.TYPE_ADDR
857 p.From.Offset = -base.Ctxt.FixedFrameSize()
858 p.From.Name = obj.NAME_PARAM
859 p.To.Type = obj.TYPE_REG
860 p.To.Reg = v.Reg()
861 case ssa.OpARMLoweredGetCallerPC:
862 p := s.Prog(obj.AGETCALLERPC)
863 p.To.Type = obj.TYPE_REG
864 p.To.Reg = v.Reg()
865 case ssa.OpARMFlagConstant:
866 v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString())
867 case ssa.OpARMInvertFlags:
868 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
869 case ssa.OpClobber, ssa.OpClobberReg:
870
871 default:
872 v.Fatalf("genValue not implemented: %s", v.LongString())
873 }
874 }
875
876 var condBits = map[ssa.Op]uint8{
877 ssa.OpARMEqual: arm.C_SCOND_EQ,
878 ssa.OpARMNotEqual: arm.C_SCOND_NE,
879 ssa.OpARMLessThan: arm.C_SCOND_LT,
880 ssa.OpARMLessThanU: arm.C_SCOND_LO,
881 ssa.OpARMLessEqual: arm.C_SCOND_LE,
882 ssa.OpARMLessEqualU: arm.C_SCOND_LS,
883 ssa.OpARMGreaterThan: arm.C_SCOND_GT,
884 ssa.OpARMGreaterThanU: arm.C_SCOND_HI,
885 ssa.OpARMGreaterEqual: arm.C_SCOND_GE,
886 ssa.OpARMGreaterEqualU: arm.C_SCOND_HS,
887 }
888
889 var blockJump = map[ssa.BlockKind]struct {
890 asm, invasm obj.As
891 }{
892 ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE},
893 ssa.BlockARMNE: {arm.ABNE, arm.ABEQ},
894 ssa.BlockARMLT: {arm.ABLT, arm.ABGE},
895 ssa.BlockARMGE: {arm.ABGE, arm.ABLT},
896 ssa.BlockARMLE: {arm.ABLE, arm.ABGT},
897 ssa.BlockARMGT: {arm.ABGT, arm.ABLE},
898 ssa.BlockARMULT: {arm.ABLO, arm.ABHS},
899 ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
900 ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
901 ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
902 ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL},
903 ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI},
904 }
905
906
907 var leJumps = [2][2]ssagen.IndexJump{
908 {{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}},
909 {{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}},
910 }
911
912
913 var gtJumps = [2][2]ssagen.IndexJump{
914 {{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}},
915 {{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}},
916 }
917
918 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
919 switch b.Kind {
920 case ssa.BlockPlain:
921 if b.Succs[0].Block() != next {
922 p := s.Prog(obj.AJMP)
923 p.To.Type = obj.TYPE_BRANCH
924 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
925 }
926
927 case ssa.BlockDefer:
928
929
930
931 p := s.Prog(arm.ACMP)
932 p.From.Type = obj.TYPE_CONST
933 p.From.Offset = 0
934 p.Reg = arm.REG_R0
935 p = s.Prog(arm.ABNE)
936 p.To.Type = obj.TYPE_BRANCH
937 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
938 if b.Succs[0].Block() != next {
939 p := s.Prog(obj.AJMP)
940 p.To.Type = obj.TYPE_BRANCH
941 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
942 }
943
944 case ssa.BlockExit, ssa.BlockRetJmp:
945
946 case ssa.BlockRet:
947 s.Prog(obj.ARET)
948
949 case ssa.BlockARMEQ, ssa.BlockARMNE,
950 ssa.BlockARMLT, ssa.BlockARMGE,
951 ssa.BlockARMLE, ssa.BlockARMGT,
952 ssa.BlockARMULT, ssa.BlockARMUGT,
953 ssa.BlockARMULE, ssa.BlockARMUGE,
954 ssa.BlockARMLTnoov, ssa.BlockARMGEnoov:
955 jmp := blockJump[b.Kind]
956 switch next {
957 case b.Succs[0].Block():
958 s.Br(jmp.invasm, b.Succs[1].Block())
959 case b.Succs[1].Block():
960 s.Br(jmp.asm, b.Succs[0].Block())
961 default:
962 if b.Likely != ssa.BranchUnlikely {
963 s.Br(jmp.asm, b.Succs[0].Block())
964 s.Br(obj.AJMP, b.Succs[1].Block())
965 } else {
966 s.Br(jmp.invasm, b.Succs[1].Block())
967 s.Br(obj.AJMP, b.Succs[0].Block())
968 }
969 }
970
971 case ssa.BlockARMLEnoov:
972 s.CombJump(b, next, &leJumps)
973
974 case ssa.BlockARMGTnoov:
975 s.CombJump(b, next, >Jumps)
976
977 default:
978 b.Fatalf("branch not implemented: %s", b.LongString())
979 }
980 }
981
View as plain text