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