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