github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/compile/internal/ppc64/prog.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ppc64
     6  
     7  import (
     8  	"cmd/compile/internal/gc"
     9  	"cmd/internal/obj"
    10  	"cmd/internal/obj/ppc64"
    11  )
    12  
    13  const (
    14  	LeftRdwr  uint32 = gc.LeftRead | gc.LeftWrite
    15  	RightRdwr uint32 = gc.RightRead | gc.RightWrite
    16  )
    17  
    18  // This table gives the basic information about instruction
    19  // generated by the compiler and processed in the optimizer.
    20  // See opt.h for bit definitions.
    21  //
    22  // Instructions not generated need not be listed.
    23  // As an exception to that rule, we typically write down all the
    24  // size variants of an operation even if we just use a subset.
    25  //
    26  // The table is formatted for 8-space tabs.
    27  var progtable = [ppc64.ALAST & obj.AMask]obj.ProgInfo{
    28  	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
    29  	obj.ATEXT:     {Flags: gc.Pseudo},
    30  	obj.AFUNCDATA: {Flags: gc.Pseudo},
    31  	obj.APCDATA:   {Flags: gc.Pseudo},
    32  	obj.AUNDEF:    {Flags: gc.Break},
    33  	obj.AUSEFIELD: {Flags: gc.OK},
    34  	obj.ACHECKNIL: {Flags: gc.LeftRead},
    35  	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
    36  	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
    37  	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
    38  
    39  	// NOP is an internal no-op that also stands
    40  	// for USED and SET annotations, not the Power opcode.
    41  	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
    42  
    43  	// Integer
    44  	ppc64.AADD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    45  	ppc64.ASUB & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    46  	ppc64.ANEG & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    47  	ppc64.AAND & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    48  	ppc64.AOR & obj.AMask:     {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    49  	ppc64.AXOR & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    50  	ppc64.AMULLD & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    51  	ppc64.AMULLW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
    52  	ppc64.AMULHD & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
    53  	ppc64.AMULHDU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
    54  	ppc64.ADIVD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    55  	ppc64.ADIVDU & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    56  	ppc64.ASLD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    57  	ppc64.ASRD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    58  	ppc64.ASRAD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
    59  	ppc64.ACMP & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
    60  	ppc64.ACMPU & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
    61  	ppc64.ATD & obj.AMask:     {Flags: gc.SizeQ | gc.RightRead},
    62  
    63  	// Floating point.
    64  	ppc64.AFADD & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
    65  	ppc64.AFADDS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    66  	ppc64.AFSUB & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
    67  	ppc64.AFSUBS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    68  	ppc64.AFMUL & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
    69  	ppc64.AFMULS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    70  	ppc64.AFDIV & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
    71  	ppc64.AFDIVS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    72  	ppc64.AFCTIDZ & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    73  	ppc64.AFCFID & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    74  	ppc64.AFCMPU & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
    75  	ppc64.AFRSP & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
    76  	ppc64.AFSQRT & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
    77  
    78  	// Moves
    79  	ppc64.AMOVB & obj.AMask:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    80  	ppc64.AMOVBU & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    81  	ppc64.AMOVBZ & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    82  	ppc64.AMOVH & obj.AMask:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    83  	ppc64.AMOVHU & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    84  	ppc64.AMOVHZ & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    85  	ppc64.AMOVW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    86  
    87  	// there is no AMOVWU.
    88  	ppc64.AMOVWZU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    89  	ppc64.AMOVWZ & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    90  	ppc64.AMOVD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
    91  	ppc64.AMOVDU & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
    92  	ppc64.AFMOVS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    93  	ppc64.AFMOVD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
    94  
    95  	// Jumps
    96  	ppc64.ABR & obj.AMask:  {Flags: gc.Jump | gc.Break},
    97  	ppc64.ABL & obj.AMask:  {Flags: gc.Call},
    98  	ppc64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
    99  	ppc64.ABNE & obj.AMask: {Flags: gc.Cjmp},
   100  	ppc64.ABGE & obj.AMask: {Flags: gc.Cjmp},
   101  	ppc64.ABLT & obj.AMask: {Flags: gc.Cjmp},
   102  	ppc64.ABGT & obj.AMask: {Flags: gc.Cjmp},
   103  	ppc64.ABLE & obj.AMask: {Flags: gc.Cjmp},
   104  	obj.ARET:               {Flags: gc.Break},
   105  	obj.ADUFFZERO:          {Flags: gc.Call},
   106  	obj.ADUFFCOPY:          {Flags: gc.Call},
   107  }
   108  
   109  func initproginfo() {
   110  	var addvariant = []int{V_CC, V_V, V_CC | V_V}
   111  
   112  	// Perform one-time expansion of instructions in progtable to
   113  	// their CC, V, and VCC variants
   114  	for i := range progtable {
   115  		as := obj.As(i)
   116  		if progtable[as].Flags == 0 {
   117  			continue
   118  		}
   119  		variant := as2variant(as)
   120  		for i := range addvariant {
   121  			as2 := variant2as(as, variant|addvariant[i])
   122  			if as2 != 0 && progtable[as2&obj.AMask].Flags == 0 {
   123  				progtable[as2&obj.AMask] = progtable[as]
   124  			}
   125  		}
   126  	}
   127  }
   128  
   129  func proginfo(p *obj.Prog) {
   130  	info := &p.Info
   131  	*info = progtable[p.As&obj.AMask]
   132  	if info.Flags == 0 {
   133  		gc.Fatalf("proginfo: unknown instruction %v", p)
   134  	}
   135  
   136  	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
   137  		info.Flags &^= gc.RegRead
   138  		info.Flags |= gc.RightRead /*CanRegRead |*/
   139  	}
   140  
   141  	if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
   142  		info.Regindex |= RtoB(int(p.From.Reg))
   143  		if info.Flags&gc.PostInc != 0 {
   144  			info.Regset |= RtoB(int(p.From.Reg))
   145  		}
   146  	}
   147  
   148  	if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
   149  		info.Regindex |= RtoB(int(p.To.Reg))
   150  		if info.Flags&gc.PostInc != 0 {
   151  			info.Regset |= RtoB(int(p.To.Reg))
   152  		}
   153  	}
   154  
   155  	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
   156  		info.Flags &^= gc.LeftRead
   157  		info.Flags |= gc.LeftAddr
   158  	}
   159  
   160  	if p.As == obj.ADUFFZERO {
   161  		info.Reguse |= 1<<0 | RtoB(ppc64.REG_R3)
   162  		info.Regset |= RtoB(ppc64.REG_R3)
   163  	}
   164  
   165  	if p.As == obj.ADUFFCOPY {
   166  		// TODO(austin) Revisit when duffcopy is implemented
   167  		info.Reguse |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4) | RtoB(ppc64.REG_R5)
   168  
   169  		info.Regset |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4)
   170  	}
   171  }
   172  
   173  // Instruction variants table, populated by initvariants via Main.
   174  // The index is the base form of the instruction, masked by obj.AMask.
   175  // The 4 values are the unmasked base form, then the unmasked CC, V,
   176  // and VCC variants, respectively.
   177  var varianttable = [ppc64.ALAST & obj.AMask][4]obj.As{}
   178  
   179  func initvariant(as obj.As, variants ...obj.As) {
   180  	vv := &varianttable[as&obj.AMask]
   181  	vv[0] = as
   182  	for i, v := range variants {
   183  		vv[i+1] = v
   184  	}
   185  }
   186  
   187  func initvariants() {
   188  	initvariant(ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC)
   189  	initvariant(ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC)
   190  	initvariant(ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC)
   191  	initvariant(ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC)
   192  	initvariant(ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC)
   193  	initvariant(ppc64.AAND, ppc64.AANDCC)
   194  	initvariant(ppc64.AANDN, ppc64.AANDNCC)
   195  	initvariant(ppc64.ACNTLZD, ppc64.ACNTLZDCC)
   196  	initvariant(ppc64.ACNTLZW, ppc64.ACNTLZWCC)
   197  	initvariant(ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC)
   198  	initvariant(ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC)
   199  	initvariant(ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC)
   200  	initvariant(ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC)
   201  	initvariant(ppc64.AEQV, ppc64.AEQVCC)
   202  	initvariant(ppc64.AEXTSB, ppc64.AEXTSBCC)
   203  	initvariant(ppc64.AEXTSH, ppc64.AEXTSHCC)
   204  	initvariant(ppc64.AEXTSW, ppc64.AEXTSWCC)
   205  	initvariant(ppc64.AFABS, ppc64.AFABSCC)
   206  	initvariant(ppc64.AFADD, ppc64.AFADDCC)
   207  	initvariant(ppc64.AFADDS, ppc64.AFADDSCC)
   208  	initvariant(ppc64.AFCFID, ppc64.AFCFIDCC)
   209  	initvariant(ppc64.AFCTID, ppc64.AFCTIDCC)
   210  	initvariant(ppc64.AFCTIDZ, ppc64.AFCTIDZCC)
   211  	initvariant(ppc64.AFCTIW, ppc64.AFCTIWCC)
   212  	initvariant(ppc64.AFCTIWZ, ppc64.AFCTIWZCC)
   213  	initvariant(ppc64.AFDIV, ppc64.AFDIVCC)
   214  	initvariant(ppc64.AFDIVS, ppc64.AFDIVSCC)
   215  	initvariant(ppc64.AFMADD, ppc64.AFMADDCC)
   216  	initvariant(ppc64.AFMADDS, ppc64.AFMADDSCC)
   217  	initvariant(ppc64.AFMOVD, ppc64.AFMOVDCC)
   218  	initvariant(ppc64.AFMSUB, ppc64.AFMSUBCC)
   219  	initvariant(ppc64.AFMSUBS, ppc64.AFMSUBSCC)
   220  	initvariant(ppc64.AFMUL, ppc64.AFMULCC)
   221  	initvariant(ppc64.AFMULS, ppc64.AFMULSCC)
   222  	initvariant(ppc64.AFNABS, ppc64.AFNABSCC)
   223  	initvariant(ppc64.AFNEG, ppc64.AFNEGCC)
   224  	initvariant(ppc64.AFNMADD, ppc64.AFNMADDCC)
   225  	initvariant(ppc64.AFNMADDS, ppc64.AFNMADDSCC)
   226  	initvariant(ppc64.AFNMSUB, ppc64.AFNMSUBCC)
   227  	initvariant(ppc64.AFNMSUBS, ppc64.AFNMSUBSCC)
   228  	initvariant(ppc64.AFRES, ppc64.AFRESCC)
   229  	initvariant(ppc64.AFRSP, ppc64.AFRSPCC)
   230  	initvariant(ppc64.AFRSQRTE, ppc64.AFRSQRTECC)
   231  	initvariant(ppc64.AFSEL, ppc64.AFSELCC)
   232  	initvariant(ppc64.AFSQRT, ppc64.AFSQRTCC)
   233  	initvariant(ppc64.AFSQRTS, ppc64.AFSQRTSCC)
   234  	initvariant(ppc64.AFSUB, ppc64.AFSUBCC)
   235  	initvariant(ppc64.AFSUBS, ppc64.AFSUBSCC)
   236  	initvariant(ppc64.AMTFSB0, ppc64.AMTFSB0CC)
   237  	initvariant(ppc64.AMTFSB1, ppc64.AMTFSB1CC)
   238  	initvariant(ppc64.AMULHD, ppc64.AMULHDCC)
   239  	initvariant(ppc64.AMULHDU, ppc64.AMULHDUCC)
   240  	initvariant(ppc64.AMULHW, ppc64.AMULHWCC)
   241  	initvariant(ppc64.AMULHWU, ppc64.AMULHWUCC)
   242  	initvariant(ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC)
   243  	initvariant(ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC)
   244  	initvariant(ppc64.ANAND, ppc64.ANANDCC)
   245  	initvariant(ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC)
   246  	initvariant(ppc64.ANOR, ppc64.ANORCC)
   247  	initvariant(ppc64.AOR, ppc64.AORCC)
   248  	initvariant(ppc64.AORN, ppc64.AORNCC)
   249  	initvariant(ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC)
   250  	initvariant(ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC)
   251  	initvariant(ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC)
   252  	initvariant(ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC)
   253  	initvariant(ppc64.ARLDC, ppc64.ARLDCCC)
   254  	initvariant(ppc64.ARLDCL, ppc64.ARLDCLCC)
   255  	initvariant(ppc64.ARLDCR, ppc64.ARLDCRCC)
   256  	initvariant(ppc64.ARLDMI, ppc64.ARLDMICC)
   257  	initvariant(ppc64.ARLWMI, ppc64.ARLWMICC)
   258  	initvariant(ppc64.ARLWNM, ppc64.ARLWNMCC)
   259  	initvariant(ppc64.ASLD, ppc64.ASLDCC)
   260  	initvariant(ppc64.ASLW, ppc64.ASLWCC)
   261  	initvariant(ppc64.ASRAD, ppc64.ASRADCC)
   262  	initvariant(ppc64.ASRAW, ppc64.ASRAWCC)
   263  	initvariant(ppc64.ASRD, ppc64.ASRDCC)
   264  	initvariant(ppc64.ASRW, ppc64.ASRWCC)
   265  	initvariant(ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC)
   266  	initvariant(ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC)
   267  	initvariant(ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC)
   268  	initvariant(ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC)
   269  	initvariant(ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC)
   270  	initvariant(ppc64.AXOR, ppc64.AXORCC)
   271  
   272  	for i := range varianttable {
   273  		vv := &varianttable[i]
   274  		if vv[0] == 0 {
   275  			// Instruction has no variants
   276  			varianttable[i][0] = obj.As(i)
   277  			continue
   278  		}
   279  
   280  		// Copy base form to other variants
   281  		if vv[0]&obj.AMask == obj.As(i) {
   282  			for _, v := range vv {
   283  				if v != 0 {
   284  					varianttable[v&obj.AMask] = varianttable[i]
   285  				}
   286  			}
   287  		}
   288  	}
   289  }
   290  
   291  // as2variant returns the variant (V_*) flags of instruction as.
   292  func as2variant(as obj.As) int {
   293  	for i, v := range varianttable[as&obj.AMask] {
   294  		if v&obj.AMask == as&obj.AMask {
   295  			return i
   296  		}
   297  	}
   298  	gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as&obj.AMask))
   299  	return 0
   300  }
   301  
   302  // variant2as returns the instruction as with the given variant (V_*) flags.
   303  // If no such variant exists, this returns 0.
   304  func variant2as(as obj.As, flags int) obj.As {
   305  	return varianttable[as&obj.AMask][flags]
   306  }