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