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