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