1
2
3
4
5 package ppc64
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/logopt"
11 "cmd/compile/internal/objw"
12 "cmd/compile/internal/ssa"
13 "cmd/compile/internal/ssagen"
14 "cmd/compile/internal/types"
15 "cmd/internal/obj"
16 "cmd/internal/obj/ppc64"
17 "internal/buildcfg"
18 "math"
19 "strings"
20 )
21
22
23 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 }
44
45
46 func loadByType(t *types.Type) obj.As {
47 if t.IsFloat() {
48 switch t.Size() {
49 case 4:
50 return ppc64.AFMOVS
51 case 8:
52 return ppc64.AFMOVD
53 }
54 } else {
55 switch t.Size() {
56 case 1:
57 if t.IsSigned() {
58 return ppc64.AMOVB
59 } else {
60 return ppc64.AMOVBZ
61 }
62 case 2:
63 if t.IsSigned() {
64 return ppc64.AMOVH
65 } else {
66 return ppc64.AMOVHZ
67 }
68 case 4:
69 if t.IsSigned() {
70 return ppc64.AMOVW
71 } else {
72 return ppc64.AMOVWZ
73 }
74 case 8:
75 return ppc64.AMOVD
76 }
77 }
78 panic("bad load type")
79 }
80
81
82 func storeByType(t *types.Type) obj.As {
83 if t.IsFloat() {
84 switch t.Size() {
85 case 4:
86 return ppc64.AFMOVS
87 case 8:
88 return ppc64.AFMOVD
89 }
90 } else {
91 switch t.Size() {
92 case 1:
93 return ppc64.AMOVB
94 case 2:
95 return ppc64.AMOVH
96 case 4:
97 return ppc64.AMOVW
98 case 8:
99 return ppc64.AMOVD
100 }
101 }
102 panic("bad store type")
103 }
104
105 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
106 switch v.Op {
107 case ssa.OpCopy:
108 t := v.Type
109 if t.IsMemory() {
110 return
111 }
112 x := v.Args[0].Reg()
113 y := v.Reg()
114 if x != y {
115 rt := obj.TYPE_REG
116 op := ppc64.AMOVD
117
118 if t.IsFloat() {
119 op = ppc64.AFMOVD
120 }
121 p := s.Prog(op)
122 p.From.Type = rt
123 p.From.Reg = x
124 p.To.Type = rt
125 p.To.Reg = y
126 }
127
128 case ssa.OpPPC64LoweredAtomicAnd8,
129 ssa.OpPPC64LoweredAtomicAnd32,
130 ssa.OpPPC64LoweredAtomicOr8,
131 ssa.OpPPC64LoweredAtomicOr32:
132
133
134
135
136
137
138 ld := ppc64.ALBAR
139 st := ppc64.ASTBCCC
140 if v.Op == ssa.OpPPC64LoweredAtomicAnd32 || v.Op == ssa.OpPPC64LoweredAtomicOr32 {
141 ld = ppc64.ALWAR
142 st = ppc64.ASTWCCC
143 }
144 r0 := v.Args[0].Reg()
145 r1 := v.Args[1].Reg()
146
147
148 plwsync := s.Prog(ppc64.ALWSYNC)
149 plwsync.To.Type = obj.TYPE_NONE
150
151 p := s.Prog(ld)
152 p.From.Type = obj.TYPE_MEM
153 p.From.Reg = r0
154 p.To.Type = obj.TYPE_REG
155 p.To.Reg = ppc64.REGTMP
156
157 p1 := s.Prog(v.Op.Asm())
158 p1.From.Type = obj.TYPE_REG
159 p1.From.Reg = r1
160 p1.To.Type = obj.TYPE_REG
161 p1.To.Reg = ppc64.REGTMP
162
163 p2 := s.Prog(st)
164 p2.From.Type = obj.TYPE_REG
165 p2.From.Reg = ppc64.REGTMP
166 p2.To.Type = obj.TYPE_MEM
167 p2.To.Reg = r0
168 p2.RegTo2 = ppc64.REGTMP
169
170 p3 := s.Prog(ppc64.ABNE)
171 p3.To.Type = obj.TYPE_BRANCH
172 p3.To.SetTarget(p)
173
174
175
176 s.Prog(ppc64.ALWSYNC)
177
178 case ssa.OpPPC64LoweredAtomicAdd32,
179 ssa.OpPPC64LoweredAtomicAdd64:
180
181
182
183
184
185
186
187 ld := ppc64.ALDAR
188 st := ppc64.ASTDCCC
189 if v.Op == ssa.OpPPC64LoweredAtomicAdd32 {
190 ld = ppc64.ALWAR
191 st = ppc64.ASTWCCC
192 }
193 r0 := v.Args[0].Reg()
194 r1 := v.Args[1].Reg()
195 out := v.Reg0()
196
197
198
199 s.Prog(ppc64.ALWSYNC)
200
201 p := s.Prog(ld)
202 p.From.Type = obj.TYPE_MEM
203 p.From.Reg = r0
204 p.To.Type = obj.TYPE_REG
205 p.To.Reg = out
206
207 p1 := s.Prog(ppc64.AADD)
208 p1.From.Type = obj.TYPE_REG
209 p1.From.Reg = r1
210 p1.To.Reg = out
211 p1.To.Type = obj.TYPE_REG
212
213 p3 := s.Prog(st)
214 p3.From.Type = obj.TYPE_REG
215 p3.From.Reg = out
216 p3.To.Type = obj.TYPE_MEM
217 p3.To.Reg = r0
218
219 p4 := s.Prog(ppc64.ABNE)
220 p4.To.Type = obj.TYPE_BRANCH
221 p4.To.SetTarget(p)
222
223
224 if v.Op == ssa.OpPPC64LoweredAtomicAdd32 {
225 p5 := s.Prog(ppc64.AMOVWZ)
226 p5.To.Type = obj.TYPE_REG
227 p5.To.Reg = out
228 p5.From.Type = obj.TYPE_REG
229 p5.From.Reg = out
230 }
231
232
233
234 plwsync2 := s.Prog(ppc64.ALWSYNC)
235 plwsync2.To.Type = obj.TYPE_NONE
236
237 case ssa.OpPPC64LoweredAtomicExchange8,
238 ssa.OpPPC64LoweredAtomicExchange32,
239 ssa.OpPPC64LoweredAtomicExchange64:
240
241
242
243
244
245 ld := ppc64.ALDAR
246 st := ppc64.ASTDCCC
247 switch v.Op {
248 case ssa.OpPPC64LoweredAtomicExchange8:
249 ld = ppc64.ALBAR
250 st = ppc64.ASTBCCC
251 case ssa.OpPPC64LoweredAtomicExchange32:
252 ld = ppc64.ALWAR
253 st = ppc64.ASTWCCC
254 }
255 r0 := v.Args[0].Reg()
256 r1 := v.Args[1].Reg()
257 out := v.Reg0()
258
259
260 plwsync := s.Prog(ppc64.ALWSYNC)
261 plwsync.To.Type = obj.TYPE_NONE
262
263 p := s.Prog(ld)
264 p.From.Type = obj.TYPE_MEM
265 p.From.Reg = r0
266 p.To.Type = obj.TYPE_REG
267 p.To.Reg = out
268
269 p1 := s.Prog(st)
270 p1.From.Type = obj.TYPE_REG
271 p1.From.Reg = r1
272 p1.To.Type = obj.TYPE_MEM
273 p1.To.Reg = r0
274
275 p2 := s.Prog(ppc64.ABNE)
276 p2.To.Type = obj.TYPE_BRANCH
277 p2.To.SetTarget(p)
278
279 pisync := s.Prog(ppc64.AISYNC)
280 pisync.To.Type = obj.TYPE_NONE
281
282 case ssa.OpPPC64LoweredAtomicLoad8,
283 ssa.OpPPC64LoweredAtomicLoad32,
284 ssa.OpPPC64LoweredAtomicLoad64,
285 ssa.OpPPC64LoweredAtomicLoadPtr:
286
287
288
289
290
291 ld := ppc64.AMOVD
292 cmp := ppc64.ACMP
293 switch v.Op {
294 case ssa.OpPPC64LoweredAtomicLoad8:
295 ld = ppc64.AMOVBZ
296 case ssa.OpPPC64LoweredAtomicLoad32:
297 ld = ppc64.AMOVWZ
298 cmp = ppc64.ACMPW
299 }
300 arg0 := v.Args[0].Reg()
301 out := v.Reg0()
302
303 if v.AuxInt == 1 {
304 psync := s.Prog(ppc64.ASYNC)
305 psync.To.Type = obj.TYPE_NONE
306 }
307
308 p := s.Prog(ld)
309 p.From.Type = obj.TYPE_MEM
310 p.From.Reg = arg0
311 p.To.Type = obj.TYPE_REG
312 p.To.Reg = out
313
314 p1 := s.Prog(cmp)
315 p1.From.Type = obj.TYPE_REG
316 p1.From.Reg = out
317 p1.To.Type = obj.TYPE_REG
318 p1.To.Reg = out
319
320 p2 := s.Prog(ppc64.ABNE)
321 p2.To.Type = obj.TYPE_BRANCH
322
323 pisync := s.Prog(ppc64.AISYNC)
324 pisync.To.Type = obj.TYPE_NONE
325 p2.To.SetTarget(pisync)
326
327 case ssa.OpPPC64LoweredAtomicStore8,
328 ssa.OpPPC64LoweredAtomicStore32,
329 ssa.OpPPC64LoweredAtomicStore64:
330
331
332 st := ppc64.AMOVD
333 switch v.Op {
334 case ssa.OpPPC64LoweredAtomicStore8:
335 st = ppc64.AMOVB
336 case ssa.OpPPC64LoweredAtomicStore32:
337 st = ppc64.AMOVW
338 }
339 arg0 := v.Args[0].Reg()
340 arg1 := v.Args[1].Reg()
341
342
343 syncOp := ppc64.ASYNC
344 if v.AuxInt == 0 {
345 syncOp = ppc64.ALWSYNC
346 }
347 psync := s.Prog(syncOp)
348 psync.To.Type = obj.TYPE_NONE
349
350 p := s.Prog(st)
351 p.To.Type = obj.TYPE_MEM
352 p.To.Reg = arg0
353 p.From.Type = obj.TYPE_REG
354 p.From.Reg = arg1
355
356 case ssa.OpPPC64LoweredAtomicCas64,
357 ssa.OpPPC64LoweredAtomicCas32:
358
359
360
361
362
363
364
365
366
367
368
369 ld := ppc64.ALDAR
370 st := ppc64.ASTDCCC
371 cmp := ppc64.ACMP
372 if v.Op == ssa.OpPPC64LoweredAtomicCas32 {
373 ld = ppc64.ALWAR
374 st = ppc64.ASTWCCC
375 cmp = ppc64.ACMPW
376 }
377 r0 := v.Args[0].Reg()
378 r1 := v.Args[1].Reg()
379 r2 := v.Args[2].Reg()
380 out := v.Reg0()
381
382 p := s.Prog(ppc64.AMOVD)
383 p.From.Type = obj.TYPE_CONST
384 p.From.Offset = 0
385 p.To.Type = obj.TYPE_REG
386 p.To.Reg = out
387
388
389 plwsync1 := s.Prog(ppc64.ALWSYNC)
390 plwsync1.To.Type = obj.TYPE_NONE
391
392 p0 := s.Prog(ld)
393 p0.From.Type = obj.TYPE_MEM
394 p0.From.Reg = r0
395 p0.To.Type = obj.TYPE_REG
396 p0.To.Reg = ppc64.REGTMP
397
398
399 if v.AuxInt == 0 {
400 p0.AddRestSourceConst(0)
401 }
402
403 p1 := s.Prog(cmp)
404 p1.From.Type = obj.TYPE_REG
405 p1.From.Reg = r1
406 p1.To.Reg = ppc64.REGTMP
407 p1.To.Type = obj.TYPE_REG
408
409 p2 := s.Prog(ppc64.ABNE)
410 p2.To.Type = obj.TYPE_BRANCH
411
412 p3 := s.Prog(st)
413 p3.From.Type = obj.TYPE_REG
414 p3.From.Reg = r2
415 p3.To.Type = obj.TYPE_MEM
416 p3.To.Reg = r0
417
418 p4 := s.Prog(ppc64.ABNE)
419 p4.To.Type = obj.TYPE_BRANCH
420 p4.To.SetTarget(p0)
421
422 p5 := s.Prog(ppc64.AMOVD)
423 p5.From.Type = obj.TYPE_CONST
424 p5.From.Offset = 1
425 p5.To.Type = obj.TYPE_REG
426 p5.To.Reg = out
427
428
429
430 if v.AuxInt != 0 {
431 plwsync2 := s.Prog(ppc64.ALWSYNC)
432 plwsync2.To.Type = obj.TYPE_NONE
433 p2.To.SetTarget(plwsync2)
434 } else {
435
436 p6 := s.Prog(obj.ANOP)
437 p2.To.SetTarget(p6)
438 }
439
440 case ssa.OpPPC64LoweredPubBarrier:
441
442 s.Prog(v.Op.Asm())
443
444 case ssa.OpPPC64LoweredGetClosurePtr:
445
446 ssagen.CheckLoweredGetClosurePtr(v)
447
448 case ssa.OpPPC64LoweredGetCallerSP:
449
450 p := s.Prog(ppc64.AMOVD)
451 p.From.Type = obj.TYPE_ADDR
452 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
453 p.From.Name = obj.NAME_PARAM
454 p.To.Type = obj.TYPE_REG
455 p.To.Reg = v.Reg()
456
457 case ssa.OpPPC64LoweredGetCallerPC:
458 p := s.Prog(obj.AGETCALLERPC)
459 p.To.Type = obj.TYPE_REG
460 p.To.Reg = v.Reg()
461
462 case ssa.OpPPC64LoweredRound32F, ssa.OpPPC64LoweredRound64F:
463
464
465 case ssa.OpLoadReg:
466 loadOp := loadByType(v.Type)
467 p := s.Prog(loadOp)
468 ssagen.AddrAuto(&p.From, v.Args[0])
469 p.To.Type = obj.TYPE_REG
470 p.To.Reg = v.Reg()
471
472 case ssa.OpStoreReg:
473 storeOp := storeByType(v.Type)
474 p := s.Prog(storeOp)
475 p.From.Type = obj.TYPE_REG
476 p.From.Reg = v.Args[0].Reg()
477 ssagen.AddrAuto(&p.To, v)
478
479 case ssa.OpArgIntReg, ssa.OpArgFloatReg:
480
481
482 for _, a := range v.Block.Func.RegArgs {
483
484
485 addr := ssagen.SpillSlotAddr(a, ppc64.REGSP, base.Ctxt.Arch.FixedFrameSize)
486 s.FuncInfo().AddSpill(
487 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
488 }
489 v.Block.Func.RegArgs = nil
490
491 ssagen.CheckArgReg(v)
492
493 case ssa.OpPPC64DIVD:
494
495
496
497
498
499
500
501
502 r := v.Reg()
503 r0 := v.Args[0].Reg()
504 r1 := v.Args[1].Reg()
505
506 p := s.Prog(ppc64.ACMP)
507 p.From.Type = obj.TYPE_REG
508 p.From.Reg = r1
509 p.To.Type = obj.TYPE_CONST
510 p.To.Offset = -1
511
512 pbahead := s.Prog(ppc64.ABEQ)
513 pbahead.To.Type = obj.TYPE_BRANCH
514
515 p = s.Prog(v.Op.Asm())
516 p.From.Type = obj.TYPE_REG
517 p.From.Reg = r1
518 p.Reg = r0
519 p.To.Type = obj.TYPE_REG
520 p.To.Reg = r
521
522 pbover := s.Prog(obj.AJMP)
523 pbover.To.Type = obj.TYPE_BRANCH
524
525 p = s.Prog(ppc64.ANEG)
526 p.To.Type = obj.TYPE_REG
527 p.To.Reg = r
528 p.From.Type = obj.TYPE_REG
529 p.From.Reg = r0
530 pbahead.To.SetTarget(p)
531
532 p = s.Prog(obj.ANOP)
533 pbover.To.SetTarget(p)
534
535 case ssa.OpPPC64DIVW:
536
537 r := v.Reg()
538 r0 := v.Args[0].Reg()
539 r1 := v.Args[1].Reg()
540
541 p := s.Prog(ppc64.ACMPW)
542 p.From.Type = obj.TYPE_REG
543 p.From.Reg = r1
544 p.To.Type = obj.TYPE_CONST
545 p.To.Offset = -1
546
547 pbahead := s.Prog(ppc64.ABEQ)
548 pbahead.To.Type = obj.TYPE_BRANCH
549
550 p = s.Prog(v.Op.Asm())
551 p.From.Type = obj.TYPE_REG
552 p.From.Reg = r1
553 p.Reg = r0
554 p.To.Type = obj.TYPE_REG
555 p.To.Reg = r
556
557 pbover := s.Prog(obj.AJMP)
558 pbover.To.Type = obj.TYPE_BRANCH
559
560 p = s.Prog(ppc64.ANEG)
561 p.To.Type = obj.TYPE_REG
562 p.To.Reg = r
563 p.From.Type = obj.TYPE_REG
564 p.From.Reg = r0
565 pbahead.To.SetTarget(p)
566
567 p = s.Prog(obj.ANOP)
568 pbover.To.SetTarget(p)
569
570 case ssa.OpPPC64CLRLSLWI:
571 r := v.Reg()
572 r1 := v.Args[0].Reg()
573 shifts := v.AuxInt
574 p := s.Prog(v.Op.Asm())
575
576 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftmb(shifts)}
577 p.AddRestSourceConst(ssa.GetPPC64Shiftsh(shifts))
578 p.Reg = r1
579 p.To.Type = obj.TYPE_REG
580 p.To.Reg = r
581
582 case ssa.OpPPC64CLRLSLDI:
583 r := v.Reg()
584 r1 := v.Args[0].Reg()
585 shifts := v.AuxInt
586 p := s.Prog(v.Op.Asm())
587
588 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: ssa.GetPPC64Shiftmb(shifts)}
589 p.AddRestSourceConst(ssa.GetPPC64Shiftsh(shifts))
590 p.Reg = r1
591 p.To.Type = obj.TYPE_REG
592 p.To.Reg = r
593
594 case ssa.OpPPC64ADD, ssa.OpPPC64FADD, ssa.OpPPC64FADDS, ssa.OpPPC64SUB, ssa.OpPPC64FSUB, ssa.OpPPC64FSUBS,
595 ssa.OpPPC64MULLD, ssa.OpPPC64MULLW, ssa.OpPPC64DIVDU, ssa.OpPPC64DIVWU,
596 ssa.OpPPC64SRAD, ssa.OpPPC64SRAW, ssa.OpPPC64SRD, ssa.OpPPC64SRW, ssa.OpPPC64SLD, ssa.OpPPC64SLW,
597 ssa.OpPPC64ROTL, ssa.OpPPC64ROTLW,
598 ssa.OpPPC64MULHD, ssa.OpPPC64MULHW, ssa.OpPPC64MULHDU, ssa.OpPPC64MULHWU,
599 ssa.OpPPC64FMUL, ssa.OpPPC64FMULS, ssa.OpPPC64FDIV, ssa.OpPPC64FDIVS, ssa.OpPPC64FCPSGN,
600 ssa.OpPPC64AND, ssa.OpPPC64OR, ssa.OpPPC64ANDN, ssa.OpPPC64ORN, ssa.OpPPC64NOR, ssa.OpPPC64XOR, ssa.OpPPC64EQV,
601 ssa.OpPPC64MODUD, ssa.OpPPC64MODSD, ssa.OpPPC64MODUW, ssa.OpPPC64MODSW, ssa.OpPPC64XSMINJDP, ssa.OpPPC64XSMAXJDP:
602 r := v.Reg()
603 r1 := v.Args[0].Reg()
604 r2 := v.Args[1].Reg()
605 p := s.Prog(v.Op.Asm())
606 p.From.Type = obj.TYPE_REG
607 p.From.Reg = r2
608 p.Reg = r1
609 p.To.Type = obj.TYPE_REG
610 p.To.Reg = r
611
612 case ssa.OpPPC64ADDCC, ssa.OpPPC64ANDCC, ssa.OpPPC64SUBCC, ssa.OpPPC64ORCC, ssa.OpPPC64XORCC, ssa.OpPPC64NORCC,
613 ssa.OpPPC64ANDNCC, ssa.OpPPC64MULHDUCC:
614 r1 := v.Args[0].Reg()
615 r2 := v.Args[1].Reg()
616 p := s.Prog(v.Op.Asm())
617 p.From.Type = obj.TYPE_REG
618 p.From.Reg = r2
619 p.Reg = r1
620 p.To.Type = obj.TYPE_REG
621 p.To.Reg = v.Reg0()
622
623 case ssa.OpPPC64NEGCC, ssa.OpPPC64CNTLZDCC:
624 p := s.Prog(v.Op.Asm())
625 p.To.Type = obj.TYPE_REG
626 p.To.Reg = v.Reg0()
627 p.From.Type = obj.TYPE_REG
628 p.From.Reg = v.Args[0].Reg()
629
630 case ssa.OpPPC64ROTLconst, ssa.OpPPC64ROTLWconst:
631 p := s.Prog(v.Op.Asm())
632 p.From.Type = obj.TYPE_CONST
633 p.From.Offset = v.AuxInt
634 p.Reg = v.Args[0].Reg()
635 p.To.Type = obj.TYPE_REG
636 p.To.Reg = v.Reg()
637
638
639 case ssa.OpPPC64RLWINM, ssa.OpPPC64RLWMI:
640 sh, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
641 p := s.Prog(v.Op.Asm())
642 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
643 p.Reg = v.Args[0].Reg()
644 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(sh)}
645 p.AddRestSourceArgs([]obj.Addr{{Type: obj.TYPE_CONST, Offset: mb}, {Type: obj.TYPE_CONST, Offset: me}})
646
647
648 case ssa.OpPPC64RLDICL, ssa.OpPPC64RLDICLCC, ssa.OpPPC64RLDICR:
649 sh, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
650 p := s.Prog(v.Op.Asm())
651 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: sh}
652 switch v.Op {
653 case ssa.OpPPC64RLDICL, ssa.OpPPC64RLDICLCC:
654 p.AddRestSourceConst(mb)
655 case ssa.OpPPC64RLDICR:
656 p.AddRestSourceConst(me)
657 }
658 p.Reg = v.Args[0].Reg()
659 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.ResultReg()}
660
661 case ssa.OpPPC64RLWNM:
662 _, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
663 p := s.Prog(v.Op.Asm())
664 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
665 p.Reg = v.Args[0].Reg()
666 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: v.Args[1].Reg()}
667 p.AddRestSourceArgs([]obj.Addr{{Type: obj.TYPE_CONST, Offset: mb}, {Type: obj.TYPE_CONST, Offset: me}})
668
669 case ssa.OpPPC64MADDLD:
670 r := v.Reg()
671 r1 := v.Args[0].Reg()
672 r2 := v.Args[1].Reg()
673 r3 := v.Args[2].Reg()
674
675 p := s.Prog(v.Op.Asm())
676 p.From.Type = obj.TYPE_REG
677 p.From.Reg = r1
678 p.Reg = r2
679 p.AddRestSourceReg(r3)
680 p.To.Type = obj.TYPE_REG
681 p.To.Reg = r
682
683 case ssa.OpPPC64FMADD, ssa.OpPPC64FMADDS, ssa.OpPPC64FMSUB, ssa.OpPPC64FMSUBS:
684 r := v.Reg()
685 r1 := v.Args[0].Reg()
686 r2 := v.Args[1].Reg()
687 r3 := v.Args[2].Reg()
688
689 p := s.Prog(v.Op.Asm())
690 p.From.Type = obj.TYPE_REG
691 p.From.Reg = r1
692 p.Reg = r3
693 p.AddRestSourceReg(r2)
694 p.To.Type = obj.TYPE_REG
695 p.To.Reg = r
696
697 case ssa.OpPPC64NEG, ssa.OpPPC64FNEG, ssa.OpPPC64FSQRT, ssa.OpPPC64FSQRTS, ssa.OpPPC64FFLOOR, ssa.OpPPC64FTRUNC, ssa.OpPPC64FCEIL,
698 ssa.OpPPC64FCTIDZ, ssa.OpPPC64FCTIWZ, ssa.OpPPC64FCFID, ssa.OpPPC64FCFIDS, ssa.OpPPC64FRSP, ssa.OpPPC64CNTLZD, ssa.OpPPC64CNTLZW,
699 ssa.OpPPC64POPCNTD, ssa.OpPPC64POPCNTW, ssa.OpPPC64POPCNTB, ssa.OpPPC64MFVSRD, ssa.OpPPC64MTVSRD, ssa.OpPPC64FABS, ssa.OpPPC64FNABS,
700 ssa.OpPPC64FROUND, ssa.OpPPC64CNTTZW, ssa.OpPPC64CNTTZD, ssa.OpPPC64BRH, ssa.OpPPC64BRW, ssa.OpPPC64BRD:
701 r := v.Reg()
702 p := s.Prog(v.Op.Asm())
703 p.To.Type = obj.TYPE_REG
704 p.To.Reg = r
705 p.From.Type = obj.TYPE_REG
706 p.From.Reg = v.Args[0].Reg()
707
708 case ssa.OpPPC64ADDconst, ssa.OpPPC64ORconst, ssa.OpPPC64XORconst,
709 ssa.OpPPC64SRADconst, ssa.OpPPC64SRAWconst, ssa.OpPPC64SRDconst, ssa.OpPPC64SRWconst,
710 ssa.OpPPC64SLDconst, ssa.OpPPC64SLWconst, ssa.OpPPC64EXTSWSLconst, ssa.OpPPC64MULLWconst, ssa.OpPPC64MULLDconst,
711 ssa.OpPPC64ANDconst:
712 p := s.Prog(v.Op.Asm())
713 p.Reg = v.Args[0].Reg()
714 p.From.Type = obj.TYPE_CONST
715 p.From.Offset = v.AuxInt
716 p.To.Type = obj.TYPE_REG
717 p.To.Reg = v.Reg()
718
719 case ssa.OpPPC64ADDC, ssa.OpPPC64ADDE, ssa.OpPPC64SUBC, ssa.OpPPC64SUBE:
720 r := v.Reg0()
721 r1 := v.Args[0].Reg()
722 r2 := v.Args[1].Reg()
723 p := s.Prog(v.Op.Asm())
724 p.From.Type = obj.TYPE_REG
725 p.From.Reg = r2
726 p.Reg = r1
727 p.To.Type = obj.TYPE_REG
728 p.To.Reg = r
729
730 case ssa.OpPPC64ADDZE:
731 p := s.Prog(v.Op.Asm())
732 p.From.Type = obj.TYPE_REG
733 p.From.Reg = v.Args[0].Reg()
734 p.To.Type = obj.TYPE_REG
735 p.To.Reg = v.Reg0()
736
737 case ssa.OpPPC64ADDZEzero, ssa.OpPPC64SUBZEzero:
738 p := s.Prog(v.Op.Asm())
739 p.From.Type = obj.TYPE_REG
740 p.From.Reg = ppc64.REG_R0
741 p.To.Type = obj.TYPE_REG
742 p.To.Reg = v.Reg()
743
744 case ssa.OpPPC64ADDCconst:
745 p := s.Prog(v.Op.Asm())
746 p.Reg = v.Args[0].Reg()
747 p.From.Type = obj.TYPE_CONST
748 p.From.Offset = v.AuxInt
749 p.To.Type = obj.TYPE_REG
750
751 p.To.Reg = v.Reg0()
752
753 case ssa.OpPPC64SUBCconst:
754 p := s.Prog(v.Op.Asm())
755 p.AddRestSourceConst(v.AuxInt)
756 p.From.Type = obj.TYPE_REG
757 p.From.Reg = v.Args[0].Reg()
758 p.To.Type = obj.TYPE_REG
759 p.To.Reg = v.Reg0()
760
761 case ssa.OpPPC64SUBFCconst:
762 p := s.Prog(v.Op.Asm())
763 p.AddRestSourceConst(v.AuxInt)
764 p.From.Type = obj.TYPE_REG
765 p.From.Reg = v.Args[0].Reg()
766 p.To.Type = obj.TYPE_REG
767 p.To.Reg = v.Reg()
768
769 case ssa.OpPPC64ADDCCconst, ssa.OpPPC64ANDCCconst:
770 p := s.Prog(v.Op.Asm())
771 p.Reg = v.Args[0].Reg()
772 p.From.Type = obj.TYPE_CONST
773 p.From.Offset = v.AuxInt
774 p.To.Type = obj.TYPE_REG
775 p.To.Reg = v.Reg0()
776
777 case ssa.OpPPC64MOVDaddr:
778 switch v.Aux.(type) {
779 default:
780 v.Fatalf("aux in MOVDaddr is of unknown type %T", v.Aux)
781 case nil:
782
783
784
785
786 if v.AuxInt != 0 || v.Args[0].Reg() != v.Reg() {
787 p := s.Prog(ppc64.AMOVD)
788 p.From.Type = obj.TYPE_ADDR
789 p.From.Reg = v.Args[0].Reg()
790 p.From.Offset = v.AuxInt
791 p.To.Type = obj.TYPE_REG
792 p.To.Reg = v.Reg()
793 }
794
795 case *obj.LSym, ir.Node:
796 p := s.Prog(ppc64.AMOVD)
797 p.From.Type = obj.TYPE_ADDR
798 p.From.Reg = v.Args[0].Reg()
799 p.To.Type = obj.TYPE_REG
800 p.To.Reg = v.Reg()
801 ssagen.AddAux(&p.From, v)
802
803 }
804
805 case ssa.OpPPC64MOVDconst:
806 p := s.Prog(v.Op.Asm())
807 p.From.Type = obj.TYPE_CONST
808 p.From.Offset = v.AuxInt
809 p.To.Type = obj.TYPE_REG
810 p.To.Reg = v.Reg()
811
812 case ssa.OpPPC64FMOVDconst, ssa.OpPPC64FMOVSconst:
813 p := s.Prog(v.Op.Asm())
814 p.From.Type = obj.TYPE_FCONST
815 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
816 p.To.Type = obj.TYPE_REG
817 p.To.Reg = v.Reg()
818
819 case ssa.OpPPC64FCMPU, ssa.OpPPC64CMP, ssa.OpPPC64CMPW, ssa.OpPPC64CMPU, ssa.OpPPC64CMPWU:
820 p := s.Prog(v.Op.Asm())
821 p.From.Type = obj.TYPE_REG
822 p.From.Reg = v.Args[0].Reg()
823 p.To.Type = obj.TYPE_REG
824 p.To.Reg = v.Args[1].Reg()
825
826 case ssa.OpPPC64CMPconst, ssa.OpPPC64CMPUconst, ssa.OpPPC64CMPWconst, ssa.OpPPC64CMPWUconst:
827 p := s.Prog(v.Op.Asm())
828 p.From.Type = obj.TYPE_REG
829 p.From.Reg = v.Args[0].Reg()
830 p.To.Type = obj.TYPE_CONST
831 p.To.Offset = v.AuxInt
832
833 case ssa.OpPPC64MOVBreg, ssa.OpPPC64MOVBZreg, ssa.OpPPC64MOVHreg, ssa.OpPPC64MOVHZreg, ssa.OpPPC64MOVWreg, ssa.OpPPC64MOVWZreg:
834
835 p := s.Prog(v.Op.Asm())
836 p.From.Type = obj.TYPE_REG
837 p.From.Reg = v.Args[0].Reg()
838 p.To.Reg = v.Reg()
839 p.To.Type = obj.TYPE_REG
840
841 case ssa.OpPPC64MOVDload, ssa.OpPPC64MOVWload:
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856 fromAddr := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
857 ssagen.AddAux(&fromAddr, v)
858
859 genAddr := false
860
861 switch fromAddr.Name {
862 case obj.NAME_EXTERN, obj.NAME_STATIC:
863
864
865
866 genAddr = strings.HasPrefix(fromAddr.Sym.Name, "go:string") || v.Type.Alignment()%4 != 0 || fromAddr.Offset%4 != 0
867 default:
868 genAddr = fromAddr.Offset%4 != 0
869 }
870 if genAddr {
871
872 p := s.Prog(ppc64.AMOVD)
873 p.From.Type = obj.TYPE_ADDR
874 p.From.Reg = v.Args[0].Reg()
875 ssagen.AddAux(&p.From, v)
876
877
878
879
880 p.To.Type = obj.TYPE_REG
881 p.To.Reg = ppc64.REGTMP
882 fromAddr.Reg = ppc64.REGTMP
883
884
885
886
887 fromAddr.Offset = 0
888 fromAddr.Name = obj.NAME_NONE
889 fromAddr.Sym = nil
890 }
891 p := s.Prog(v.Op.Asm())
892 p.From = fromAddr
893 p.To.Type = obj.TYPE_REG
894 p.To.Reg = v.Reg()
895
896 case ssa.OpPPC64MOVHload, ssa.OpPPC64MOVWZload, ssa.OpPPC64MOVBZload, ssa.OpPPC64MOVHZload, ssa.OpPPC64FMOVDload, ssa.OpPPC64FMOVSload:
897 p := s.Prog(v.Op.Asm())
898 p.From.Type = obj.TYPE_MEM
899 p.From.Reg = v.Args[0].Reg()
900 ssagen.AddAux(&p.From, v)
901 p.To.Type = obj.TYPE_REG
902 p.To.Reg = v.Reg()
903
904 case ssa.OpPPC64MOVDBRload, ssa.OpPPC64MOVWBRload, ssa.OpPPC64MOVHBRload:
905 p := s.Prog(v.Op.Asm())
906 p.From.Type = obj.TYPE_MEM
907 p.From.Reg = v.Args[0].Reg()
908 p.To.Type = obj.TYPE_REG
909 p.To.Reg = v.Reg()
910
911 case ssa.OpPPC64MOVDBRstore, ssa.OpPPC64MOVWBRstore, ssa.OpPPC64MOVHBRstore:
912 p := s.Prog(v.Op.Asm())
913 p.To.Type = obj.TYPE_MEM
914 p.To.Reg = v.Args[0].Reg()
915 p.From.Type = obj.TYPE_REG
916 p.From.Reg = v.Args[1].Reg()
917
918 case ssa.OpPPC64MOVDloadidx, ssa.OpPPC64MOVWloadidx, ssa.OpPPC64MOVHloadidx, ssa.OpPPC64MOVWZloadidx,
919 ssa.OpPPC64MOVBZloadidx, ssa.OpPPC64MOVHZloadidx, ssa.OpPPC64FMOVDloadidx, ssa.OpPPC64FMOVSloadidx,
920 ssa.OpPPC64MOVDBRloadidx, ssa.OpPPC64MOVWBRloadidx, ssa.OpPPC64MOVHBRloadidx:
921 p := s.Prog(v.Op.Asm())
922 p.From.Type = obj.TYPE_MEM
923 p.From.Reg = v.Args[0].Reg()
924 p.From.Index = v.Args[1].Reg()
925 p.To.Type = obj.TYPE_REG
926 p.To.Reg = v.Reg()
927
928 case ssa.OpPPC64DCBT:
929 p := s.Prog(v.Op.Asm())
930 p.From.Type = obj.TYPE_MEM
931 p.From.Reg = v.Args[0].Reg()
932 p.To.Type = obj.TYPE_CONST
933 p.To.Offset = v.AuxInt
934
935 case ssa.OpPPC64MOVWstorezero, ssa.OpPPC64MOVHstorezero, ssa.OpPPC64MOVBstorezero:
936 p := s.Prog(v.Op.Asm())
937 p.From.Type = obj.TYPE_REG
938 p.From.Reg = ppc64.REGZERO
939 p.To.Type = obj.TYPE_MEM
940 p.To.Reg = v.Args[0].Reg()
941 ssagen.AddAux(&p.To, v)
942
943 case ssa.OpPPC64MOVDstore, ssa.OpPPC64MOVDstorezero:
944
945
946
947
948
949
950
951
952
953
954 toAddr := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
955 ssagen.AddAux(&toAddr, v)
956
957 if toAddr.Offset%4 != 0 {
958 p := s.Prog(ppc64.AMOVD)
959 p.From.Type = obj.TYPE_ADDR
960 p.From.Reg = v.Args[0].Reg()
961 ssagen.AddAux(&p.From, v)
962 p.To.Type = obj.TYPE_REG
963 p.To.Reg = ppc64.REGTMP
964 toAddr.Reg = ppc64.REGTMP
965
966
967
968
969 toAddr.Offset = 0
970 toAddr.Name = obj.NAME_NONE
971 toAddr.Sym = nil
972 }
973 p := s.Prog(v.Op.Asm())
974 p.To = toAddr
975 p.From.Type = obj.TYPE_REG
976 if v.Op == ssa.OpPPC64MOVDstorezero {
977 p.From.Reg = ppc64.REGZERO
978 } else {
979 p.From.Reg = v.Args[1].Reg()
980 }
981
982 case ssa.OpPPC64MOVWstore, ssa.OpPPC64MOVHstore, ssa.OpPPC64MOVBstore, ssa.OpPPC64FMOVDstore, ssa.OpPPC64FMOVSstore:
983 p := s.Prog(v.Op.Asm())
984 p.From.Type = obj.TYPE_REG
985 p.From.Reg = v.Args[1].Reg()
986 p.To.Type = obj.TYPE_MEM
987 p.To.Reg = v.Args[0].Reg()
988 ssagen.AddAux(&p.To, v)
989
990 case ssa.OpPPC64MOVDstoreidx, ssa.OpPPC64MOVWstoreidx, ssa.OpPPC64MOVHstoreidx, ssa.OpPPC64MOVBstoreidx,
991 ssa.OpPPC64FMOVDstoreidx, ssa.OpPPC64FMOVSstoreidx, ssa.OpPPC64MOVDBRstoreidx, ssa.OpPPC64MOVWBRstoreidx,
992 ssa.OpPPC64MOVHBRstoreidx:
993 p := s.Prog(v.Op.Asm())
994 p.From.Type = obj.TYPE_REG
995 p.From.Reg = v.Args[2].Reg()
996 p.To.Index = v.Args[1].Reg()
997 p.To.Type = obj.TYPE_MEM
998 p.To.Reg = v.Args[0].Reg()
999
1000 case ssa.OpPPC64ISEL, ssa.OpPPC64ISELZ:
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 p := s.Prog(v.Op.Asm())
1011 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
1012 p.Reg = v.Args[0].Reg()
1013 if v.Op == ssa.OpPPC64ISEL {
1014 p.AddRestSourceReg(v.Args[1].Reg())
1015 } else {
1016 p.AddRestSourceReg(ppc64.REG_R0)
1017 }
1018
1019 if v.AuxInt > 3 {
1020 p.Reg, p.GetFrom3().Reg = p.GetFrom3().Reg, p.Reg
1021 }
1022 p.From.SetConst(v.AuxInt & 3)
1023
1024 case ssa.OpPPC64SETBC, ssa.OpPPC64SETBCR:
1025 p := s.Prog(v.Op.Asm())
1026 p.To.Type = obj.TYPE_REG
1027 p.To.Reg = v.Reg()
1028 p.From.Type = obj.TYPE_REG
1029 p.From.Reg = int16(ppc64.REG_CR0LT + v.AuxInt)
1030
1031 case ssa.OpPPC64LoweredQuadZero, ssa.OpPPC64LoweredQuadZeroShort:
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 ctr := v.AuxInt / 64
1054
1055
1056 rem := v.AuxInt % 64
1057
1058
1059
1060 if ctr > 1 {
1061
1062 p := s.Prog(ppc64.AXXLXOR)
1063 p.From.Type = obj.TYPE_REG
1064 p.From.Reg = ppc64.REG_VS32
1065 p.To.Type = obj.TYPE_REG
1066 p.To.Reg = ppc64.REG_VS32
1067 p.Reg = ppc64.REG_VS32
1068
1069
1070 p = s.Prog(ppc64.AMOVD)
1071 p.From.Type = obj.TYPE_CONST
1072 p.From.Offset = ctr
1073 p.To.Type = obj.TYPE_REG
1074 p.To.Reg = ppc64.REGTMP
1075
1076 p = s.Prog(ppc64.AMOVD)
1077 p.From.Type = obj.TYPE_REG
1078 p.From.Reg = ppc64.REGTMP
1079 p.To.Type = obj.TYPE_REG
1080 p.To.Reg = ppc64.REG_CTR
1081
1082
1083
1084 if ctr > 3 {
1085 p = s.Prog(obj.APCALIGN)
1086 p.From.Type = obj.TYPE_CONST
1087 p.From.Offset = 16
1088 }
1089
1090
1091 var top *obj.Prog
1092
1093 p = s.Prog(ppc64.ASTXV)
1094 p.From.Type = obj.TYPE_REG
1095 p.From.Reg = ppc64.REG_VS32
1096 p.To.Type = obj.TYPE_MEM
1097 p.To.Reg = v.Args[0].Reg()
1098
1099
1100 if top == nil {
1101 top = p
1102 }
1103 p = s.Prog(ppc64.ASTXV)
1104 p.From.Type = obj.TYPE_REG
1105 p.From.Reg = ppc64.REG_VS32
1106 p.To.Type = obj.TYPE_MEM
1107 p.To.Reg = v.Args[0].Reg()
1108 p.To.Offset = 16
1109
1110 p = s.Prog(ppc64.ASTXV)
1111 p.From.Type = obj.TYPE_REG
1112 p.From.Reg = ppc64.REG_VS32
1113 p.To.Type = obj.TYPE_MEM
1114 p.To.Reg = v.Args[0].Reg()
1115 p.To.Offset = 32
1116
1117 p = s.Prog(ppc64.ASTXV)
1118 p.From.Type = obj.TYPE_REG
1119 p.From.Reg = ppc64.REG_VS32
1120 p.To.Type = obj.TYPE_MEM
1121 p.To.Reg = v.Args[0].Reg()
1122 p.To.Offset = 48
1123
1124
1125
1126 p = s.Prog(ppc64.AADD)
1127 p.Reg = v.Args[0].Reg()
1128 p.From.Type = obj.TYPE_CONST
1129 p.From.Offset = 64
1130 p.To.Type = obj.TYPE_REG
1131 p.To.Reg = v.Args[0].Reg()
1132
1133
1134
1135
1136 p = s.Prog(ppc64.ABC)
1137 p.From.Type = obj.TYPE_CONST
1138 p.From.Offset = ppc64.BO_BCTR
1139 p.Reg = ppc64.REG_CR0LT
1140 p.To.Type = obj.TYPE_BRANCH
1141 p.To.SetTarget(top)
1142 }
1143
1144
1145
1146
1147 if ctr == 1 {
1148 rem += 64
1149 }
1150
1151
1152 offset := int64(0)
1153
1154 if rem >= 16 && ctr <= 1 {
1155
1156
1157
1158 p := s.Prog(ppc64.AXXLXOR)
1159 p.From.Type = obj.TYPE_REG
1160 p.From.Reg = ppc64.REG_VS32
1161 p.To.Type = obj.TYPE_REG
1162 p.To.Reg = ppc64.REG_VS32
1163 p.Reg = ppc64.REG_VS32
1164 }
1165
1166
1167 for rem >= 32 {
1168 p := s.Prog(ppc64.ASTXV)
1169 p.From.Type = obj.TYPE_REG
1170 p.From.Reg = ppc64.REG_VS32
1171 p.To.Type = obj.TYPE_MEM
1172 p.To.Reg = v.Args[0].Reg()
1173 p.To.Offset = offset
1174
1175 p = s.Prog(ppc64.ASTXV)
1176 p.From.Type = obj.TYPE_REG
1177 p.From.Reg = ppc64.REG_VS32
1178 p.To.Type = obj.TYPE_MEM
1179 p.To.Reg = v.Args[0].Reg()
1180 p.To.Offset = offset + 16
1181 offset += 32
1182 rem -= 32
1183 }
1184
1185 if rem >= 16 {
1186 p := s.Prog(ppc64.ASTXV)
1187 p.From.Type = obj.TYPE_REG
1188 p.From.Reg = ppc64.REG_VS32
1189 p.To.Type = obj.TYPE_MEM
1190 p.To.Reg = v.Args[0].Reg()
1191 p.To.Offset = offset
1192 offset += 16
1193 rem -= 16
1194 }
1195
1196
1197
1198 for rem > 0 {
1199 op, size := ppc64.AMOVB, int64(1)
1200 switch {
1201 case rem >= 8:
1202 op, size = ppc64.AMOVD, 8
1203 case rem >= 4:
1204 op, size = ppc64.AMOVW, 4
1205 case rem >= 2:
1206 op, size = ppc64.AMOVH, 2
1207 }
1208 p := s.Prog(op)
1209 p.From.Type = obj.TYPE_REG
1210 p.From.Reg = ppc64.REG_R0
1211 p.To.Type = obj.TYPE_MEM
1212 p.To.Reg = v.Args[0].Reg()
1213 p.To.Offset = offset
1214 rem -= size
1215 offset += size
1216 }
1217
1218 case ssa.OpPPC64LoweredZero, ssa.OpPPC64LoweredZeroShort:
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258 ctr := v.AuxInt / 32
1259
1260
1261 rem := v.AuxInt % 32
1262
1263
1264
1265 if ctr > 1 {
1266
1267 p := s.Prog(ppc64.AXXLXOR)
1268 p.From.Type = obj.TYPE_REG
1269 p.From.Reg = ppc64.REG_VS32
1270 p.To.Type = obj.TYPE_REG
1271 p.To.Reg = ppc64.REG_VS32
1272 p.Reg = ppc64.REG_VS32
1273
1274
1275 p = s.Prog(ppc64.AMOVD)
1276 p.From.Type = obj.TYPE_CONST
1277 p.From.Offset = ctr
1278 p.To.Type = obj.TYPE_REG
1279 p.To.Reg = ppc64.REGTMP
1280
1281 p = s.Prog(ppc64.AMOVD)
1282 p.From.Type = obj.TYPE_REG
1283 p.From.Reg = ppc64.REGTMP
1284 p.To.Type = obj.TYPE_REG
1285 p.To.Reg = ppc64.REG_CTR
1286
1287
1288 p = s.Prog(ppc64.AMOVD)
1289 p.From.Type = obj.TYPE_CONST
1290 p.From.Offset = 16
1291 p.To.Type = obj.TYPE_REG
1292 p.To.Reg = ppc64.REGTMP
1293
1294
1295
1296 if ctr > 3 {
1297 p = s.Prog(obj.APCALIGN)
1298 p.From.Type = obj.TYPE_CONST
1299 p.From.Offset = 16
1300 }
1301
1302
1303
1304 var top *obj.Prog
1305
1306
1307 p = s.Prog(ppc64.ASTXVD2X)
1308 p.From.Type = obj.TYPE_REG
1309 p.From.Reg = ppc64.REG_VS32
1310 p.To.Type = obj.TYPE_MEM
1311 p.To.Reg = v.Args[0].Reg()
1312 p.To.Index = ppc64.REGZERO
1313
1314 if top == nil {
1315 top = p
1316 }
1317 p = s.Prog(ppc64.ASTXVD2X)
1318 p.From.Type = obj.TYPE_REG
1319 p.From.Reg = ppc64.REG_VS32
1320 p.To.Type = obj.TYPE_MEM
1321 p.To.Reg = v.Args[0].Reg()
1322 p.To.Index = ppc64.REGTMP
1323
1324
1325
1326 p = s.Prog(ppc64.AADD)
1327 p.Reg = v.Args[0].Reg()
1328 p.From.Type = obj.TYPE_CONST
1329 p.From.Offset = 32
1330 p.To.Type = obj.TYPE_REG
1331 p.To.Reg = v.Args[0].Reg()
1332
1333
1334
1335
1336 p = s.Prog(ppc64.ABC)
1337 p.From.Type = obj.TYPE_CONST
1338 p.From.Offset = ppc64.BO_BCTR
1339 p.Reg = ppc64.REG_CR0LT
1340 p.To.Type = obj.TYPE_BRANCH
1341 p.To.SetTarget(top)
1342 }
1343
1344
1345
1346
1347
1348 if ctr == 1 {
1349 rem += 32
1350 }
1351
1352
1353 offset := int64(0)
1354
1355
1356
1357 for rem > 0 {
1358 op, size := ppc64.AMOVB, int64(1)
1359 switch {
1360 case rem >= 8:
1361 op, size = ppc64.AMOVD, 8
1362 case rem >= 4:
1363 op, size = ppc64.AMOVW, 4
1364 case rem >= 2:
1365 op, size = ppc64.AMOVH, 2
1366 }
1367 p := s.Prog(op)
1368 p.From.Type = obj.TYPE_REG
1369 p.From.Reg = ppc64.REG_R0
1370 p.To.Type = obj.TYPE_MEM
1371 p.To.Reg = v.Args[0].Reg()
1372 p.To.Offset = offset
1373 rem -= size
1374 offset += size
1375 }
1376
1377 case ssa.OpPPC64LoweredMove, ssa.OpPPC64LoweredMoveShort:
1378
1379 bytesPerLoop := int64(32)
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417 ctr := v.AuxInt / bytesPerLoop
1418
1419
1420 rem := v.AuxInt % bytesPerLoop
1421
1422 dstReg := v.Args[0].Reg()
1423 srcReg := v.Args[1].Reg()
1424
1425
1426
1427 offset := int64(0)
1428
1429
1430 var top *obj.Prog
1431
1432 if ctr > 1 {
1433
1434 p := s.Prog(ppc64.AMOVD)
1435 p.From.Type = obj.TYPE_CONST
1436 p.From.Offset = ctr
1437 p.To.Type = obj.TYPE_REG
1438 p.To.Reg = ppc64.REGTMP
1439
1440 p = s.Prog(ppc64.AMOVD)
1441 p.From.Type = obj.TYPE_REG
1442 p.From.Reg = ppc64.REGTMP
1443 p.To.Type = obj.TYPE_REG
1444 p.To.Reg = ppc64.REG_CTR
1445
1446
1447 p = s.Prog(ppc64.AMOVD)
1448 p.From.Type = obj.TYPE_CONST
1449 p.From.Offset = 16
1450 p.To.Type = obj.TYPE_REG
1451 p.To.Reg = ppc64.REGTMP
1452
1453
1454
1455
1456 if ctr > 3 {
1457 p = s.Prog(obj.APCALIGN)
1458 p.From.Type = obj.TYPE_CONST
1459 p.From.Offset = 16
1460 }
1461
1462
1463
1464
1465
1466 p = s.Prog(ppc64.ALXVD2X)
1467 p.From.Type = obj.TYPE_MEM
1468 p.From.Reg = srcReg
1469 p.From.Index = ppc64.REGZERO
1470 p.To.Type = obj.TYPE_REG
1471 p.To.Reg = ppc64.REG_VS32
1472 if top == nil {
1473 top = p
1474 }
1475 p = s.Prog(ppc64.ALXVD2X)
1476 p.From.Type = obj.TYPE_MEM
1477 p.From.Reg = srcReg
1478 p.From.Index = ppc64.REGTMP
1479 p.To.Type = obj.TYPE_REG
1480 p.To.Reg = ppc64.REG_VS33
1481
1482
1483 p = s.Prog(ppc64.AADD)
1484 p.Reg = srcReg
1485 p.From.Type = obj.TYPE_CONST
1486 p.From.Offset = bytesPerLoop
1487 p.To.Type = obj.TYPE_REG
1488 p.To.Reg = srcReg
1489
1490
1491 p = s.Prog(ppc64.ASTXVD2X)
1492 p.From.Type = obj.TYPE_REG
1493 p.From.Reg = ppc64.REG_VS32
1494 p.To.Type = obj.TYPE_MEM
1495 p.To.Reg = dstReg
1496 p.To.Index = ppc64.REGZERO
1497
1498 p = s.Prog(ppc64.ASTXVD2X)
1499 p.From.Type = obj.TYPE_REG
1500 p.From.Reg = ppc64.REG_VS33
1501 p.To.Type = obj.TYPE_MEM
1502 p.To.Reg = dstReg
1503 p.To.Index = ppc64.REGTMP
1504
1505
1506 p = s.Prog(ppc64.AADD)
1507 p.Reg = dstReg
1508 p.From.Type = obj.TYPE_CONST
1509 p.From.Offset = bytesPerLoop
1510 p.To.Type = obj.TYPE_REG
1511 p.To.Reg = dstReg
1512
1513
1514
1515 p = s.Prog(ppc64.ABC)
1516 p.From.Type = obj.TYPE_CONST
1517 p.From.Offset = ppc64.BO_BCTR
1518 p.Reg = ppc64.REG_CR0LT
1519 p.To.Type = obj.TYPE_BRANCH
1520 p.To.SetTarget(top)
1521
1522
1523
1524 offset = int64(0)
1525 }
1526
1527
1528
1529 if ctr == 1 {
1530 rem += bytesPerLoop
1531 }
1532
1533 if rem >= 16 {
1534
1535
1536
1537 p := s.Prog(ppc64.ALXVD2X)
1538 p.From.Type = obj.TYPE_MEM
1539 p.From.Reg = srcReg
1540 p.From.Index = ppc64.REGZERO
1541 p.To.Type = obj.TYPE_REG
1542 p.To.Reg = ppc64.REG_VS32
1543
1544 p = s.Prog(ppc64.ASTXVD2X)
1545 p.From.Type = obj.TYPE_REG
1546 p.From.Reg = ppc64.REG_VS32
1547 p.To.Type = obj.TYPE_MEM
1548 p.To.Reg = dstReg
1549 p.To.Index = ppc64.REGZERO
1550
1551 offset = 16
1552 rem -= 16
1553
1554 if rem >= 16 {
1555
1556 p := s.Prog(ppc64.AMOVD)
1557 p.From.Type = obj.TYPE_CONST
1558 p.From.Offset = 16
1559 p.To.Type = obj.TYPE_REG
1560 p.To.Reg = ppc64.REGTMP
1561
1562 p = s.Prog(ppc64.ALXVD2X)
1563 p.From.Type = obj.TYPE_MEM
1564 p.From.Reg = srcReg
1565 p.From.Index = ppc64.REGTMP
1566 p.To.Type = obj.TYPE_REG
1567 p.To.Reg = ppc64.REG_VS32
1568
1569 p = s.Prog(ppc64.ASTXVD2X)
1570 p.From.Type = obj.TYPE_REG
1571 p.From.Reg = ppc64.REG_VS32
1572 p.To.Type = obj.TYPE_MEM
1573 p.To.Reg = dstReg
1574 p.To.Index = ppc64.REGTMP
1575
1576 offset = 32
1577 rem -= 16
1578 }
1579 }
1580
1581
1582
1583 for rem > 0 {
1584 op, size := ppc64.AMOVB, int64(1)
1585 switch {
1586 case rem >= 8:
1587 op, size = ppc64.AMOVD, 8
1588 case rem >= 4:
1589 op, size = ppc64.AMOVWZ, 4
1590 case rem >= 2:
1591 op, size = ppc64.AMOVH, 2
1592 }
1593
1594 p := s.Prog(op)
1595 p.To.Type = obj.TYPE_REG
1596 p.To.Reg = ppc64.REGTMP
1597 p.From.Type = obj.TYPE_MEM
1598 p.From.Reg = srcReg
1599 p.From.Offset = offset
1600
1601
1602 p = s.Prog(op)
1603 p.From.Type = obj.TYPE_REG
1604 p.From.Reg = ppc64.REGTMP
1605 p.To.Type = obj.TYPE_MEM
1606 p.To.Reg = dstReg
1607 p.To.Offset = offset
1608 rem -= size
1609 offset += size
1610 }
1611
1612 case ssa.OpPPC64LoweredQuadMove, ssa.OpPPC64LoweredQuadMoveShort:
1613 bytesPerLoop := int64(64)
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650 ctr := v.AuxInt / bytesPerLoop
1651
1652
1653 rem := v.AuxInt % bytesPerLoop
1654
1655 dstReg := v.Args[0].Reg()
1656 srcReg := v.Args[1].Reg()
1657
1658 offset := int64(0)
1659
1660
1661 var top *obj.Prog
1662
1663
1664 if ctr > 1 {
1665
1666 p := s.Prog(ppc64.AMOVD)
1667 p.From.Type = obj.TYPE_CONST
1668 p.From.Offset = ctr
1669 p.To.Type = obj.TYPE_REG
1670 p.To.Reg = ppc64.REGTMP
1671
1672 p = s.Prog(ppc64.AMOVD)
1673 p.From.Type = obj.TYPE_REG
1674 p.From.Reg = ppc64.REGTMP
1675 p.To.Type = obj.TYPE_REG
1676 p.To.Reg = ppc64.REG_CTR
1677
1678 p = s.Prog(obj.APCALIGN)
1679 p.From.Type = obj.TYPE_CONST
1680 p.From.Offset = 16
1681
1682
1683 p = s.Prog(ppc64.ALXV)
1684 p.From.Type = obj.TYPE_MEM
1685 p.From.Reg = srcReg
1686 p.From.Offset = offset
1687 p.To.Type = obj.TYPE_REG
1688 p.To.Reg = ppc64.REG_VS32
1689 if top == nil {
1690 top = p
1691 }
1692 p = s.Prog(ppc64.ALXV)
1693 p.From.Type = obj.TYPE_MEM
1694 p.From.Reg = srcReg
1695 p.From.Offset = offset + 16
1696 p.To.Type = obj.TYPE_REG
1697 p.To.Reg = ppc64.REG_VS33
1698
1699
1700 p = s.Prog(ppc64.ASTXV)
1701 p.From.Type = obj.TYPE_REG
1702 p.From.Reg = ppc64.REG_VS32
1703 p.To.Type = obj.TYPE_MEM
1704 p.To.Reg = dstReg
1705 p.To.Offset = offset
1706
1707 p = s.Prog(ppc64.ASTXV)
1708 p.From.Type = obj.TYPE_REG
1709 p.From.Reg = ppc64.REG_VS33
1710 p.To.Type = obj.TYPE_MEM
1711 p.To.Reg = dstReg
1712 p.To.Offset = offset + 16
1713
1714
1715 p = s.Prog(ppc64.ALXV)
1716 p.From.Type = obj.TYPE_MEM
1717 p.From.Reg = srcReg
1718 p.From.Offset = offset + 32
1719 p.To.Type = obj.TYPE_REG
1720 p.To.Reg = ppc64.REG_VS32
1721
1722 p = s.Prog(ppc64.ALXV)
1723 p.From.Type = obj.TYPE_MEM
1724 p.From.Reg = srcReg
1725 p.From.Offset = offset + 48
1726 p.To.Type = obj.TYPE_REG
1727 p.To.Reg = ppc64.REG_VS33
1728
1729
1730 p = s.Prog(ppc64.ASTXV)
1731 p.From.Type = obj.TYPE_REG
1732 p.From.Reg = ppc64.REG_VS32
1733 p.To.Type = obj.TYPE_MEM
1734 p.To.Reg = dstReg
1735 p.To.Offset = offset + 32
1736
1737 p = s.Prog(ppc64.ASTXV)
1738 p.From.Type = obj.TYPE_REG
1739 p.From.Reg = ppc64.REG_VS33
1740 p.To.Type = obj.TYPE_MEM
1741 p.To.Reg = dstReg
1742 p.To.Offset = offset + 48
1743
1744
1745 p = s.Prog(ppc64.AADD)
1746 p.Reg = srcReg
1747 p.From.Type = obj.TYPE_CONST
1748 p.From.Offset = bytesPerLoop
1749 p.To.Type = obj.TYPE_REG
1750 p.To.Reg = srcReg
1751
1752
1753 p = s.Prog(ppc64.AADD)
1754 p.Reg = dstReg
1755 p.From.Type = obj.TYPE_CONST
1756 p.From.Offset = bytesPerLoop
1757 p.To.Type = obj.TYPE_REG
1758 p.To.Reg = dstReg
1759
1760
1761
1762 p = s.Prog(ppc64.ABC)
1763 p.From.Type = obj.TYPE_CONST
1764 p.From.Offset = ppc64.BO_BCTR
1765 p.Reg = ppc64.REG_CR0LT
1766 p.To.Type = obj.TYPE_BRANCH
1767 p.To.SetTarget(top)
1768
1769
1770
1771 offset = int64(0)
1772 }
1773
1774
1775
1776 if ctr == 1 {
1777 rem += bytesPerLoop
1778 }
1779 if rem >= 32 {
1780 p := s.Prog(ppc64.ALXV)
1781 p.From.Type = obj.TYPE_MEM
1782 p.From.Reg = srcReg
1783 p.To.Type = obj.TYPE_REG
1784 p.To.Reg = ppc64.REG_VS32
1785
1786 p = s.Prog(ppc64.ALXV)
1787 p.From.Type = obj.TYPE_MEM
1788 p.From.Reg = srcReg
1789 p.From.Offset = 16
1790 p.To.Type = obj.TYPE_REG
1791 p.To.Reg = ppc64.REG_VS33
1792
1793 p = s.Prog(ppc64.ASTXV)
1794 p.From.Type = obj.TYPE_REG
1795 p.From.Reg = ppc64.REG_VS32
1796 p.To.Type = obj.TYPE_MEM
1797 p.To.Reg = dstReg
1798
1799 p = s.Prog(ppc64.ASTXV)
1800 p.From.Type = obj.TYPE_REG
1801 p.From.Reg = ppc64.REG_VS33
1802 p.To.Type = obj.TYPE_MEM
1803 p.To.Reg = dstReg
1804 p.To.Offset = 16
1805
1806 offset = 32
1807 rem -= 32
1808 }
1809
1810 if rem >= 16 {
1811
1812 p := s.Prog(ppc64.ALXV)
1813 p.From.Type = obj.TYPE_MEM
1814 p.From.Reg = srcReg
1815 p.From.Offset = offset
1816 p.To.Type = obj.TYPE_REG
1817 p.To.Reg = ppc64.REG_VS32
1818
1819 p = s.Prog(ppc64.ASTXV)
1820 p.From.Type = obj.TYPE_REG
1821 p.From.Reg = ppc64.REG_VS32
1822 p.To.Type = obj.TYPE_MEM
1823 p.To.Reg = dstReg
1824 p.To.Offset = offset
1825
1826 offset += 16
1827 rem -= 16
1828
1829 if rem >= 16 {
1830 p := s.Prog(ppc64.ALXV)
1831 p.From.Type = obj.TYPE_MEM
1832 p.From.Reg = srcReg
1833 p.From.Offset = offset
1834 p.To.Type = obj.TYPE_REG
1835 p.To.Reg = ppc64.REG_VS32
1836
1837 p = s.Prog(ppc64.ASTXV)
1838 p.From.Type = obj.TYPE_REG
1839 p.From.Reg = ppc64.REG_VS32
1840 p.To.Type = obj.TYPE_MEM
1841 p.To.Reg = dstReg
1842 p.To.Offset = offset
1843
1844 offset += 16
1845 rem -= 16
1846 }
1847 }
1848
1849
1850 for rem > 0 {
1851 op, size := ppc64.AMOVB, int64(1)
1852 switch {
1853 case rem >= 8:
1854 op, size = ppc64.AMOVD, 8
1855 case rem >= 4:
1856 op, size = ppc64.AMOVWZ, 4
1857 case rem >= 2:
1858 op, size = ppc64.AMOVH, 2
1859 }
1860
1861 p := s.Prog(op)
1862 p.To.Type = obj.TYPE_REG
1863 p.To.Reg = ppc64.REGTMP
1864 p.From.Type = obj.TYPE_MEM
1865 p.From.Reg = srcReg
1866 p.From.Offset = offset
1867
1868
1869 p = s.Prog(op)
1870 p.From.Type = obj.TYPE_REG
1871 p.From.Reg = ppc64.REGTMP
1872 p.To.Type = obj.TYPE_MEM
1873 p.To.Reg = dstReg
1874 p.To.Offset = offset
1875 rem -= size
1876 offset += size
1877 }
1878
1879 case ssa.OpPPC64CALLstatic:
1880 s.Call(v)
1881
1882 case ssa.OpPPC64CALLtail:
1883 s.TailCall(v)
1884
1885 case ssa.OpPPC64CALLclosure, ssa.OpPPC64CALLinter:
1886 p := s.Prog(ppc64.AMOVD)
1887 p.From.Type = obj.TYPE_REG
1888 p.From.Reg = v.Args[0].Reg()
1889 p.To.Type = obj.TYPE_REG
1890 p.To.Reg = ppc64.REG_LR
1891
1892 if v.Args[0].Reg() != ppc64.REG_R12 {
1893 v.Fatalf("Function address for %v should be in R12 %d but is in %d", v.LongString(), ppc64.REG_R12, p.From.Reg)
1894 }
1895
1896 pp := s.Call(v)
1897
1898
1899
1900 pp.As = ppc64.ABCL
1901 pp.From.Type = obj.TYPE_CONST
1902 pp.From.Offset = ppc64.BO_ALWAYS
1903 pp.Reg = ppc64.REG_CR0LT
1904 pp.To.Reg = ppc64.REG_LR
1905 pp.AddRestSourceConst(1)
1906
1907 if ppc64.NeedTOCpointer(base.Ctxt) {
1908
1909
1910
1911
1912 q := s.Prog(ppc64.AMOVD)
1913 q.From.Type = obj.TYPE_MEM
1914 q.From.Offset = 24
1915 q.From.Reg = ppc64.REGSP
1916 q.To.Type = obj.TYPE_REG
1917 q.To.Reg = ppc64.REG_R2
1918 }
1919
1920 case ssa.OpPPC64LoweredWB:
1921 p := s.Prog(obj.ACALL)
1922 p.To.Type = obj.TYPE_MEM
1923 p.To.Name = obj.NAME_EXTERN
1924
1925 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
1926
1927 case ssa.OpPPC64LoweredPanicBoundsA, ssa.OpPPC64LoweredPanicBoundsB, ssa.OpPPC64LoweredPanicBoundsC:
1928 p := s.Prog(obj.ACALL)
1929 p.To.Type = obj.TYPE_MEM
1930 p.To.Name = obj.NAME_EXTERN
1931 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
1932 s.UseArgs(16)
1933
1934 case ssa.OpPPC64LoweredNilCheck:
1935 if buildcfg.GOOS == "aix" {
1936
1937
1938
1939
1940
1941
1942 p := s.Prog(ppc64.ACMP)
1943 p.From.Type = obj.TYPE_REG
1944 p.From.Reg = v.Args[0].Reg()
1945 p.To.Type = obj.TYPE_CONST
1946 p.To.Offset = 0
1947
1948
1949 p2 := s.Prog(ppc64.ABNE)
1950 p2.To.Type = obj.TYPE_BRANCH
1951
1952
1953
1954 p = s.Prog(ppc64.AMOVW)
1955 p.From.Type = obj.TYPE_REG
1956 p.From.Reg = ppc64.REG_R0
1957 p.To.Type = obj.TYPE_MEM
1958 p.To.Reg = ppc64.REG_R0
1959
1960
1961 nop := s.Prog(obj.ANOP)
1962 p2.To.SetTarget(nop)
1963
1964 } else {
1965
1966 p := s.Prog(ppc64.AMOVBZ)
1967 p.From.Type = obj.TYPE_MEM
1968 p.From.Reg = v.Args[0].Reg()
1969 ssagen.AddAux(&p.From, v)
1970 p.To.Type = obj.TYPE_REG
1971 p.To.Reg = ppc64.REGTMP
1972 }
1973 if logopt.Enabled() {
1974 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
1975 }
1976 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
1977 base.WarnfAt(v.Pos, "generated nil check")
1978 }
1979
1980
1981 case ssa.OpPPC64Equal, ssa.OpPPC64NotEqual, ssa.OpPPC64LessThan, ssa.OpPPC64FLessThan,
1982 ssa.OpPPC64LessEqual, ssa.OpPPC64GreaterThan, ssa.OpPPC64FGreaterThan, ssa.OpPPC64GreaterEqual,
1983 ssa.OpPPC64FLessEqual, ssa.OpPPC64FGreaterEqual:
1984 v.Fatalf("Pseudo-op should not make it to codegen: %s ###\n", v.LongString())
1985 case ssa.OpPPC64InvertFlags:
1986 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
1987 case ssa.OpPPC64FlagEQ, ssa.OpPPC64FlagLT, ssa.OpPPC64FlagGT:
1988 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
1989 case ssa.OpClobber, ssa.OpClobberReg:
1990
1991 default:
1992 v.Fatalf("genValue not implemented: %s", v.LongString())
1993 }
1994 }
1995
1996 var blockJump = [...]struct {
1997 asm, invasm obj.As
1998 asmeq, invasmun bool
1999 }{
2000 ssa.BlockPPC64EQ: {ppc64.ABEQ, ppc64.ABNE, false, false},
2001 ssa.BlockPPC64NE: {ppc64.ABNE, ppc64.ABEQ, false, false},
2002
2003 ssa.BlockPPC64LT: {ppc64.ABLT, ppc64.ABGE, false, false},
2004 ssa.BlockPPC64GE: {ppc64.ABGE, ppc64.ABLT, false, false},
2005 ssa.BlockPPC64LE: {ppc64.ABLE, ppc64.ABGT, false, false},
2006 ssa.BlockPPC64GT: {ppc64.ABGT, ppc64.ABLE, false, false},
2007
2008
2009 ssa.BlockPPC64FLT: {ppc64.ABLT, ppc64.ABGE, false, false},
2010 ssa.BlockPPC64FGE: {ppc64.ABGT, ppc64.ABLT, true, true},
2011 ssa.BlockPPC64FLE: {ppc64.ABLT, ppc64.ABGT, true, true},
2012 ssa.BlockPPC64FGT: {ppc64.ABGT, ppc64.ABLE, false, false},
2013 }
2014
2015 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
2016 switch b.Kind {
2017 case ssa.BlockPlain, ssa.BlockDefer:
2018 if b.Succs[0].Block() != next {
2019 p := s.Prog(obj.AJMP)
2020 p.To.Type = obj.TYPE_BRANCH
2021 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
2022 }
2023 case ssa.BlockExit, ssa.BlockRetJmp:
2024 case ssa.BlockRet:
2025 s.Prog(obj.ARET)
2026
2027 case ssa.BlockPPC64EQ, ssa.BlockPPC64NE,
2028 ssa.BlockPPC64LT, ssa.BlockPPC64GE,
2029 ssa.BlockPPC64LE, ssa.BlockPPC64GT,
2030 ssa.BlockPPC64FLT, ssa.BlockPPC64FGE,
2031 ssa.BlockPPC64FLE, ssa.BlockPPC64FGT:
2032 jmp := blockJump[b.Kind]
2033 switch next {
2034 case b.Succs[0].Block():
2035 s.Br(jmp.invasm, b.Succs[1].Block())
2036 if jmp.invasmun {
2037
2038 s.Br(ppc64.ABVS, b.Succs[1].Block())
2039 }
2040 case b.Succs[1].Block():
2041 s.Br(jmp.asm, b.Succs[0].Block())
2042 if jmp.asmeq {
2043 s.Br(ppc64.ABEQ, b.Succs[0].Block())
2044 }
2045 default:
2046 if b.Likely != ssa.BranchUnlikely {
2047 s.Br(jmp.asm, b.Succs[0].Block())
2048 if jmp.asmeq {
2049 s.Br(ppc64.ABEQ, b.Succs[0].Block())
2050 }
2051 s.Br(obj.AJMP, b.Succs[1].Block())
2052 } else {
2053 s.Br(jmp.invasm, b.Succs[1].Block())
2054 if jmp.invasmun {
2055
2056 s.Br(ppc64.ABVS, b.Succs[1].Block())
2057 }
2058 s.Br(obj.AJMP, b.Succs[0].Block())
2059 }
2060 }
2061 default:
2062 b.Fatalf("branch not implemented: %s", b.LongString())
2063 }
2064 }
2065
2066 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
2067 p := s.Prog(loadByType(t))
2068 p.From.Type = obj.TYPE_MEM
2069 p.From.Name = obj.NAME_AUTO
2070 p.From.Sym = n.Linksym()
2071 p.From.Offset = n.FrameOffset() + off
2072 p.To.Type = obj.TYPE_REG
2073 p.To.Reg = reg
2074 return p
2075 }
2076
2077 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
2078 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
2079 p.To.Name = obj.NAME_PARAM
2080 p.To.Sym = n.Linksym()
2081 p.Pos = p.Pos.WithNotStmt()
2082 return p
2083 }
2084
View as plain text