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