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/logopt"
14 "cmd/compile/internal/ssa"
15 "cmd/compile/internal/types"
16 "cmd/internal/obj"
17 "cmd/internal/obj/arm"
18 "cmd/internal/objabi"
19 )
20
21
22 func loadByType(t *types.Type) obj.As {
23 if t.IsFloat() {
24 switch t.Size() {
25 case 4:
26 return arm.AMOVF
27 case 8:
28 return arm.AMOVD
29 }
30 } else {
31 switch t.Size() {
32 case 1:
33 if t.IsSigned() {
34 return arm.AMOVB
35 } else {
36 return arm.AMOVBU
37 }
38 case 2:
39 if t.IsSigned() {
40 return arm.AMOVH
41 } else {
42 return arm.AMOVHU
43 }
44 case 4:
45 return arm.AMOVW
46 }
47 }
48 panic("bad load type")
49 }
50
51
52 func storeByType(t *types.Type) obj.As {
53 if t.IsFloat() {
54 switch t.Size() {
55 case 4:
56 return arm.AMOVF
57 case 8:
58 return arm.AMOVD
59 }
60 } else {
61 switch t.Size() {
62 case 1:
63 return arm.AMOVB
64 case 2:
65 return arm.AMOVH
66 case 4:
67 return arm.AMOVW
68 }
69 }
70 panic("bad store type")
71 }
72
73
74 type shift int64
75
76
77 func (v shift) String() string {
78 op := "<<>>->@>"[((v>>5)&3)<<1:]
79 if v&(1<<4) != 0 {
80
81 return fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
82 } else {
83
84 return fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
85 }
86 }
87
88
89 func makeshift(reg int16, typ int64, s int64) shift {
90 return shift(int64(reg&0xf) | typ | (s&31)<<7)
91 }
92
93
94 func genshift(s *gc.SSAGenState, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog {
95 p := s.Prog(as)
96 p.From.Type = obj.TYPE_SHIFT
97 p.From.Offset = int64(makeshift(r1, typ, n))
98 p.Reg = r0
99 if r != 0 {
100 p.To.Type = obj.TYPE_REG
101 p.To.Reg = r
102 }
103 return p
104 }
105
106
107 func makeregshift(r1 int16, typ int64, r2 int16) shift {
108 return shift(int64(r1&0xf) | typ | int64(r2&0xf)<<8 | 1<<4)
109 }
110
111
112 func genregshift(s *gc.SSAGenState, as obj.As, r0, r1, r2, r int16, typ int64) *obj.Prog {
113 p := s.Prog(as)
114 p.From.Type = obj.TYPE_SHIFT
115 p.From.Offset = int64(makeregshift(r1, typ, r2))
116 p.Reg = r0
117 if r != 0 {
118 p.To.Type = obj.TYPE_REG
119 p.To.Reg = r
120 }
121 return p
122 }
123
124
125
126
127 func getBFC(v uint32) (uint32, uint32) {
128 var m, l uint32
129
130 if v == 0 {
131 return 0xffffffff, 0
132 }
133
134 l = uint32(bits.TrailingZeros32(v))
135
136 m = 32 - uint32(bits.LeadingZeros32(v))
137
138 if (1<<m)-(1<<l) == v {
139
140 return l, m - l
141 }
142
143 return 0xffffffff, 0
144 }
145
146 func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
147 switch v.Op {
148 case ssa.OpCopy, ssa.OpARMMOVWreg:
149 if v.Type.IsMemory() {
150 return
151 }
152 x := v.Args[0].Reg()
153 y := v.Reg()
154 if x == y {
155 return
156 }
157 as := arm.AMOVW
158 if v.Type.IsFloat() {
159 switch v.Type.Size() {
160 case 4:
161 as = arm.AMOVF
162 case 8:
163 as = arm.AMOVD
164 default:
165 panic("bad float size")
166 }
167 }
168 p := s.Prog(as)
169 p.From.Type = obj.TYPE_REG
170 p.From.Reg = x
171 p.To.Type = obj.TYPE_REG
172 p.To.Reg = y
173 case ssa.OpARMMOVWnop:
174 if v.Reg() != v.Args[0].Reg() {
175 v.Fatalf("input[0] and output not in same register %s", v.LongString())
176 }
177
178 case ssa.OpLoadReg:
179 if v.Type.IsFlags() {
180 v.Fatalf("load flags not implemented: %v", v.LongString())
181 return
182 }
183 p := s.Prog(loadByType(v.Type))
184 gc.AddrAuto(&p.From, v.Args[0])
185 p.To.Type = obj.TYPE_REG
186 p.To.Reg = v.Reg()
187 case ssa.OpStoreReg:
188 if v.Type.IsFlags() {
189 v.Fatalf("store flags not implemented: %v", v.LongString())
190 return
191 }
192 p := s.Prog(storeByType(v.Type))
193 p.From.Type = obj.TYPE_REG
194 p.From.Reg = v.Args[0].Reg()
195 gc.AddrAuto(&p.To, v)
196 case ssa.OpARMADD,
197 ssa.OpARMADC,
198 ssa.OpARMSUB,
199 ssa.OpARMSBC,
200 ssa.OpARMRSB,
201 ssa.OpARMAND,
202 ssa.OpARMOR,
203 ssa.OpARMXOR,
204 ssa.OpARMBIC,
205 ssa.OpARMMUL,
206 ssa.OpARMADDF,
207 ssa.OpARMADDD,
208 ssa.OpARMSUBF,
209 ssa.OpARMSUBD,
210 ssa.OpARMSLL,
211 ssa.OpARMSRL,
212 ssa.OpARMSRA,
213 ssa.OpARMMULF,
214 ssa.OpARMMULD,
215 ssa.OpARMNMULF,
216 ssa.OpARMNMULD,
217 ssa.OpARMDIVF,
218 ssa.OpARMDIVD:
219 r := v.Reg()
220 r1 := v.Args[0].Reg()
221 r2 := v.Args[1].Reg()
222 p := s.Prog(v.Op.Asm())
223 p.From.Type = obj.TYPE_REG
224 p.From.Reg = r2
225 p.Reg = r1
226 p.To.Type = obj.TYPE_REG
227 p.To.Reg = r
228 case ssa.OpARMSRR:
229 genregshift(s, arm.AMOVW, 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR)
230 case ssa.OpARMMULAF, ssa.OpARMMULAD, ssa.OpARMMULSF, ssa.OpARMMULSD, ssa.OpARMFMULAD:
231 r := v.Reg()
232 r0 := v.Args[0].Reg()
233 r1 := v.Args[1].Reg()
234 r2 := v.Args[2].Reg()
235 if r != r0 {
236 v.Fatalf("result and addend are not in the same register: %v", v.LongString())
237 }
238 p := s.Prog(v.Op.Asm())
239 p.From.Type = obj.TYPE_REG
240 p.From.Reg = r2
241 p.Reg = r1
242 p.To.Type = obj.TYPE_REG
243 p.To.Reg = r
244 case ssa.OpARMADDS,
245 ssa.OpARMSUBS:
246 r := v.Reg0()
247 r1 := v.Args[0].Reg()
248 r2 := v.Args[1].Reg()
249 p := s.Prog(v.Op.Asm())
250 p.Scond = arm.C_SBIT
251 p.From.Type = obj.TYPE_REG
252 p.From.Reg = r2
253 p.Reg = r1
254 p.To.Type = obj.TYPE_REG
255 p.To.Reg = r
256 case ssa.OpARMSRAcond:
257
258
259
260
261
262 r := v.Reg()
263 r1 := v.Args[0].Reg()
264 r2 := v.Args[1].Reg()
265 p := s.Prog(arm.ASRA)
266 p.Scond = arm.C_SCOND_HS
267 p.From.Type = obj.TYPE_CONST
268 p.From.Offset = 31
269 p.Reg = r1
270 p.To.Type = obj.TYPE_REG
271 p.To.Reg = r
272 p = s.Prog(arm.ASRA)
273 p.Scond = arm.C_SCOND_LO
274 p.From.Type = obj.TYPE_REG
275 p.From.Reg = r2
276 p.Reg = r1
277 p.To.Type = obj.TYPE_REG
278 p.To.Reg = r
279 case ssa.OpARMBFX, ssa.OpARMBFXU:
280 p := s.Prog(v.Op.Asm())
281 p.From.Type = obj.TYPE_CONST
282 p.From.Offset = v.AuxInt >> 8
283 p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: v.AuxInt & 0xff})
284 p.Reg = v.Args[0].Reg()
285 p.To.Type = obj.TYPE_REG
286 p.To.Reg = v.Reg()
287 case ssa.OpARMANDconst, ssa.OpARMBICconst:
288
289
290 if objabi.GOARM == 7 && v.Reg() == v.Args[0].Reg() {
291 var val uint32
292 if v.Op == ssa.OpARMANDconst {
293 val = ^uint32(v.AuxInt)
294 } else {
295 val = uint32(v.AuxInt)
296 }
297 lsb, width := getBFC(val)
298
299 if 8 < width && width < 24 {
300 p := s.Prog(arm.ABFC)
301 p.From.Type = obj.TYPE_CONST
302 p.From.Offset = int64(width)
303 p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: int64(lsb)})
304 p.To.Type = obj.TYPE_REG
305 p.To.Reg = v.Reg()
306 break
307 }
308 }
309
310 fallthrough
311 case ssa.OpARMADDconst,
312 ssa.OpARMADCconst,
313 ssa.OpARMSUBconst,
314 ssa.OpARMSBCconst,
315 ssa.OpARMRSBconst,
316 ssa.OpARMRSCconst,
317 ssa.OpARMORconst,
318 ssa.OpARMXORconst,
319 ssa.OpARMSLLconst,
320 ssa.OpARMSRLconst,
321 ssa.OpARMSRAconst:
322 p := s.Prog(v.Op.Asm())
323 p.From.Type = obj.TYPE_CONST
324 p.From.Offset = v.AuxInt
325 p.Reg = v.Args[0].Reg()
326 p.To.Type = obj.TYPE_REG
327 p.To.Reg = v.Reg()
328 case ssa.OpARMADDSconst,
329 ssa.OpARMSUBSconst,
330 ssa.OpARMRSBSconst:
331 p := s.Prog(v.Op.Asm())
332 p.Scond = arm.C_SBIT
333 p.From.Type = obj.TYPE_CONST
334 p.From.Offset = v.AuxInt
335 p.Reg = v.Args[0].Reg()
336 p.To.Type = obj.TYPE_REG
337 p.To.Reg = v.Reg0()
338 case ssa.OpARMSRRconst:
339 genshift(s, arm.AMOVW, 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt)
340 case ssa.OpARMADDshiftLL,
341 ssa.OpARMADCshiftLL,
342 ssa.OpARMSUBshiftLL,
343 ssa.OpARMSBCshiftLL,
344 ssa.OpARMRSBshiftLL,
345 ssa.OpARMRSCshiftLL,
346 ssa.OpARMANDshiftLL,
347 ssa.OpARMORshiftLL,
348 ssa.OpARMXORshiftLL,
349 ssa.OpARMBICshiftLL:
350 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
351 case ssa.OpARMADDSshiftLL,
352 ssa.OpARMSUBSshiftLL,
353 ssa.OpARMRSBSshiftLL:
354 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LL, v.AuxInt)
355 p.Scond = arm.C_SBIT
356 case ssa.OpARMADDshiftRL,
357 ssa.OpARMADCshiftRL,
358 ssa.OpARMSUBshiftRL,
359 ssa.OpARMSBCshiftRL,
360 ssa.OpARMRSBshiftRL,
361 ssa.OpARMRSCshiftRL,
362 ssa.OpARMANDshiftRL,
363 ssa.OpARMORshiftRL,
364 ssa.OpARMXORshiftRL,
365 ssa.OpARMBICshiftRL:
366 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
367 case ssa.OpARMADDSshiftRL,
368 ssa.OpARMSUBSshiftRL,
369 ssa.OpARMRSBSshiftRL:
370 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LR, v.AuxInt)
371 p.Scond = arm.C_SBIT
372 case ssa.OpARMADDshiftRA,
373 ssa.OpARMADCshiftRA,
374 ssa.OpARMSUBshiftRA,
375 ssa.OpARMSBCshiftRA,
376 ssa.OpARMRSBshiftRA,
377 ssa.OpARMRSCshiftRA,
378 ssa.OpARMANDshiftRA,
379 ssa.OpARMORshiftRA,
380 ssa.OpARMXORshiftRA,
381 ssa.OpARMBICshiftRA:
382 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
383 case ssa.OpARMADDSshiftRA,
384 ssa.OpARMSUBSshiftRA,
385 ssa.OpARMRSBSshiftRA:
386 p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_AR, v.AuxInt)
387 p.Scond = arm.C_SBIT
388 case ssa.OpARMXORshiftRR:
389 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt)
390 case ssa.OpARMMVNshiftLL:
391 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
392 case ssa.OpARMMVNshiftRL:
393 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
394 case ssa.OpARMMVNshiftRA:
395 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
396 case ssa.OpARMMVNshiftLLreg:
397 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL)
398 case ssa.OpARMMVNshiftRLreg:
399 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR)
400 case ssa.OpARMMVNshiftRAreg:
401 genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR)
402 case ssa.OpARMADDshiftLLreg,
403 ssa.OpARMADCshiftLLreg,
404 ssa.OpARMSUBshiftLLreg,
405 ssa.OpARMSBCshiftLLreg,
406 ssa.OpARMRSBshiftLLreg,
407 ssa.OpARMRSCshiftLLreg,
408 ssa.OpARMANDshiftLLreg,
409 ssa.OpARMORshiftLLreg,
410 ssa.OpARMXORshiftLLreg,
411 ssa.OpARMBICshiftLLreg:
412 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_LL)
413 case ssa.OpARMADDSshiftLLreg,
414 ssa.OpARMSUBSshiftLLreg,
415 ssa.OpARMRSBSshiftLLreg:
416 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_LL)
417 p.Scond = arm.C_SBIT
418 case ssa.OpARMADDshiftRLreg,
419 ssa.OpARMADCshiftRLreg,
420 ssa.OpARMSUBshiftRLreg,
421 ssa.OpARMSBCshiftRLreg,
422 ssa.OpARMRSBshiftRLreg,
423 ssa.OpARMRSCshiftRLreg,
424 ssa.OpARMANDshiftRLreg,
425 ssa.OpARMORshiftRLreg,
426 ssa.OpARMXORshiftRLreg,
427 ssa.OpARMBICshiftRLreg:
428 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_LR)
429 case ssa.OpARMADDSshiftRLreg,
430 ssa.OpARMSUBSshiftRLreg,
431 ssa.OpARMRSBSshiftRLreg:
432 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_LR)
433 p.Scond = arm.C_SBIT
434 case ssa.OpARMADDshiftRAreg,
435 ssa.OpARMADCshiftRAreg,
436 ssa.OpARMSUBshiftRAreg,
437 ssa.OpARMSBCshiftRAreg,
438 ssa.OpARMRSBshiftRAreg,
439 ssa.OpARMRSCshiftRAreg,
440 ssa.OpARMANDshiftRAreg,
441 ssa.OpARMORshiftRAreg,
442 ssa.OpARMXORshiftRAreg,
443 ssa.OpARMBICshiftRAreg:
444 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg(), arm.SHIFT_AR)
445 case ssa.OpARMADDSshiftRAreg,
446 ssa.OpARMSUBSshiftRAreg,
447 ssa.OpARMRSBSshiftRAreg:
448 p := genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), v.Reg0(), arm.SHIFT_AR)
449 p.Scond = arm.C_SBIT
450 case ssa.OpARMHMUL,
451 ssa.OpARMHMULU:
452
453 p := s.Prog(v.Op.Asm())
454 p.From.Type = obj.TYPE_REG
455 p.From.Reg = v.Args[0].Reg()
456 p.Reg = v.Args[1].Reg()
457 p.To.Type = obj.TYPE_REGREG
458 p.To.Reg = v.Reg()
459 p.To.Offset = arm.REGTMP
460 case ssa.OpARMMULLU:
461
462 p := s.Prog(v.Op.Asm())
463 p.From.Type = obj.TYPE_REG
464 p.From.Reg = v.Args[0].Reg()
465 p.Reg = v.Args[1].Reg()
466 p.To.Type = obj.TYPE_REGREG
467 p.To.Reg = v.Reg0()
468 p.To.Offset = int64(v.Reg1())
469 case ssa.OpARMMULA, ssa.OpARMMULS:
470 p := s.Prog(v.Op.Asm())
471 p.From.Type = obj.TYPE_REG
472 p.From.Reg = v.Args[0].Reg()
473 p.Reg = v.Args[1].Reg()
474 p.To.Type = obj.TYPE_REGREG2
475 p.To.Reg = v.Reg()
476 p.To.Offset = int64(v.Args[2].Reg())
477 case ssa.OpARMMOVWconst:
478 p := s.Prog(v.Op.Asm())
479 p.From.Type = obj.TYPE_CONST
480 p.From.Offset = v.AuxInt
481 p.To.Type = obj.TYPE_REG
482 p.To.Reg = v.Reg()
483 case ssa.OpARMMOVFconst,
484 ssa.OpARMMOVDconst:
485 p := s.Prog(v.Op.Asm())
486 p.From.Type = obj.TYPE_FCONST
487 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
488 p.To.Type = obj.TYPE_REG
489 p.To.Reg = v.Reg()
490 case ssa.OpARMCMP,
491 ssa.OpARMCMN,
492 ssa.OpARMTST,
493 ssa.OpARMTEQ,
494 ssa.OpARMCMPF,
495 ssa.OpARMCMPD:
496 p := s.Prog(v.Op.Asm())
497 p.From.Type = obj.TYPE_REG
498
499
500 p.From.Reg = v.Args[1].Reg()
501 p.Reg = v.Args[0].Reg()
502 case ssa.OpARMCMPconst,
503 ssa.OpARMCMNconst,
504 ssa.OpARMTSTconst,
505 ssa.OpARMTEQconst:
506
507 p := s.Prog(v.Op.Asm())
508 p.From.Type = obj.TYPE_CONST
509 p.From.Offset = v.AuxInt
510 p.Reg = v.Args[0].Reg()
511 case ssa.OpARMCMPF0,
512 ssa.OpARMCMPD0:
513 p := s.Prog(v.Op.Asm())
514 p.From.Type = obj.TYPE_REG
515 p.From.Reg = v.Args[0].Reg()
516 case ssa.OpARMCMPshiftLL, ssa.OpARMCMNshiftLL, ssa.OpARMTSTshiftLL, ssa.OpARMTEQshiftLL:
517 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LL, v.AuxInt)
518 case ssa.OpARMCMPshiftRL, ssa.OpARMCMNshiftRL, ssa.OpARMTSTshiftRL, ssa.OpARMTEQshiftRL:
519 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LR, v.AuxInt)
520 case ssa.OpARMCMPshiftRA, ssa.OpARMCMNshiftRA, ssa.OpARMTSTshiftRA, ssa.OpARMTEQshiftRA:
521 genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_AR, v.AuxInt)
522 case ssa.OpARMCMPshiftLLreg, ssa.OpARMCMNshiftLLreg, ssa.OpARMTSTshiftLLreg, ssa.OpARMTEQshiftLLreg:
523 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_LL)
524 case ssa.OpARMCMPshiftRLreg, ssa.OpARMCMNshiftRLreg, ssa.OpARMTSTshiftRLreg, ssa.OpARMTEQshiftRLreg:
525 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_LR)
526 case ssa.OpARMCMPshiftRAreg, ssa.OpARMCMNshiftRAreg, ssa.OpARMTSTshiftRAreg, ssa.OpARMTEQshiftRAreg:
527 genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_AR)
528 case ssa.OpARMMOVWaddr:
529 p := s.Prog(arm.AMOVW)
530 p.From.Type = obj.TYPE_ADDR
531 p.From.Reg = v.Args[0].Reg()
532 p.To.Type = obj.TYPE_REG
533 p.To.Reg = v.Reg()
534
535 var wantreg string
536
537
538
539
540
541 switch v.Aux.(type) {
542 default:
543 v.Fatalf("aux is of unknown type %T", v.Aux)
544 case *obj.LSym:
545 wantreg = "SB"
546 gc.AddAux(&p.From, v)
547 case *gc.Node:
548 wantreg = "SP"
549 gc.AddAux(&p.From, v)
550 case nil:
551
552 wantreg = "SP"
553 p.From.Offset = v.AuxInt
554 }
555 if reg := v.Args[0].RegName(); reg != wantreg {
556 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
557 }
558
559 case ssa.OpARMMOVBload,
560 ssa.OpARMMOVBUload,
561 ssa.OpARMMOVHload,
562 ssa.OpARMMOVHUload,
563 ssa.OpARMMOVWload,
564 ssa.OpARMMOVFload,
565 ssa.OpARMMOVDload:
566 p := s.Prog(v.Op.Asm())
567 p.From.Type = obj.TYPE_MEM
568 p.From.Reg = v.Args[0].Reg()
569 gc.AddAux(&p.From, v)
570 p.To.Type = obj.TYPE_REG
571 p.To.Reg = v.Reg()
572 case ssa.OpARMMOVBstore,
573 ssa.OpARMMOVHstore,
574 ssa.OpARMMOVWstore,
575 ssa.OpARMMOVFstore,
576 ssa.OpARMMOVDstore:
577 p := s.Prog(v.Op.Asm())
578 p.From.Type = obj.TYPE_REG
579 p.From.Reg = v.Args[1].Reg()
580 p.To.Type = obj.TYPE_MEM
581 p.To.Reg = v.Args[0].Reg()
582 gc.AddAux(&p.To, v)
583 case ssa.OpARMMOVWloadidx, ssa.OpARMMOVBUloadidx, ssa.OpARMMOVBloadidx, ssa.OpARMMOVHUloadidx, ssa.OpARMMOVHloadidx:
584
585 fallthrough
586 case ssa.OpARMMOVWloadshiftLL:
587 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt)
588 p.From.Reg = v.Args[0].Reg()
589 case ssa.OpARMMOVWloadshiftRL:
590 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt)
591 p.From.Reg = v.Args[0].Reg()
592 case ssa.OpARMMOVWloadshiftRA:
593 p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt)
594 p.From.Reg = v.Args[0].Reg()
595 case ssa.OpARMMOVWstoreidx, ssa.OpARMMOVBstoreidx, ssa.OpARMMOVHstoreidx:
596
597 fallthrough
598 case ssa.OpARMMOVWstoreshiftLL:
599 p := s.Prog(v.Op.Asm())
600 p.From.Type = obj.TYPE_REG
601 p.From.Reg = v.Args[2].Reg()
602 p.To.Type = obj.TYPE_SHIFT
603 p.To.Reg = v.Args[0].Reg()
604 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LL, v.AuxInt))
605 case ssa.OpARMMOVWstoreshiftRL:
606 p := s.Prog(v.Op.Asm())
607 p.From.Type = obj.TYPE_REG
608 p.From.Reg = v.Args[2].Reg()
609 p.To.Type = obj.TYPE_SHIFT
610 p.To.Reg = v.Args[0].Reg()
611 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LR, v.AuxInt))
612 case ssa.OpARMMOVWstoreshiftRA:
613 p := s.Prog(v.Op.Asm())
614 p.From.Type = obj.TYPE_REG
615 p.From.Reg = v.Args[2].Reg()
616 p.To.Type = obj.TYPE_SHIFT
617 p.To.Reg = v.Args[0].Reg()
618 p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_AR, v.AuxInt))
619 case ssa.OpARMMOVBreg,
620 ssa.OpARMMOVBUreg,
621 ssa.OpARMMOVHreg,
622 ssa.OpARMMOVHUreg:
623 a := v.Args[0]
624 for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg || a.Op == ssa.OpARMMOVWnop {
625 a = a.Args[0]
626 }
627 if a.Op == ssa.OpLoadReg {
628 t := a.Type
629 switch {
630 case v.Op == ssa.OpARMMOVBreg && t.Size() == 1 && t.IsSigned(),
631 v.Op == ssa.OpARMMOVBUreg && t.Size() == 1 && !t.IsSigned(),
632 v.Op == ssa.OpARMMOVHreg && t.Size() == 2 && t.IsSigned(),
633 v.Op == ssa.OpARMMOVHUreg && t.Size() == 2 && !t.IsSigned():
634
635 if v.Reg() == v.Args[0].Reg() {
636 return
637 }
638 p := s.Prog(arm.AMOVW)
639 p.From.Type = obj.TYPE_REG
640 p.From.Reg = v.Args[0].Reg()
641 p.To.Type = obj.TYPE_REG
642 p.To.Reg = v.Reg()
643 return
644 default:
645 }
646 }
647 if objabi.GOARM >= 6 {
648
649 genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0)
650 return
651 }
652 fallthrough
653 case ssa.OpARMMVN,
654 ssa.OpARMCLZ,
655 ssa.OpARMREV,
656 ssa.OpARMREV16,
657 ssa.OpARMRBIT,
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 = gc.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 = gc.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 = gc.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 = gc.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 = gc.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 gc.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 gc.Debug_checknil != 0 && v.Pos.Line() > 1 {
745 gc.Warnl(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 gc.Patch(p3, 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 gc.Patch(p4, 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 gc.CheckLoweredGetClosurePtr(v)
848 case ssa.OpARMLoweredGetCallerSP:
849
850 p := s.Prog(arm.AMOVW)
851 p.From.Type = obj.TYPE_ADDR
852 p.From.Offset = -gc.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:
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]gc.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]gc.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 *gc.SSAGenState, 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, gc.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, gc.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, gc.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