github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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.AFCFIDU & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
    75  	ppc64.AFCMPU & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
    76  	ppc64.AFRSP & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
    77  	ppc64.AFSQRT & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
    78  
    79  	// Moves
    80  	ppc64.AMOVB & obj.AMask:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    81  	ppc64.AMOVBU & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    82  	ppc64.AMOVBZ & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    83  	ppc64.AMOVH & obj.AMask:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    84  	ppc64.AMOVHU & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    85  	ppc64.AMOVHZ & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    86  	ppc64.AMOVW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    87  
    88  	// there is no AMOVWU.
    89  	ppc64.AMOVWZU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    90  	ppc64.AMOVWZ & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    91  	ppc64.AMOVD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
    92  	ppc64.AMOVDU & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
    93  	ppc64.AFMOVS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    94  	ppc64.AFMOVD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
    95  
    96  	// Jumps
    97  	ppc64.ABR & obj.AMask:  {Flags: gc.Jump | gc.Break},
    98  	ppc64.ABL & obj.AMask:  {Flags: gc.Call},
    99  	ppc64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
   100  	ppc64.ABNE & obj.AMask: {Flags: gc.Cjmp},
   101  	ppc64.ABGE & obj.AMask: {Flags: gc.Cjmp},
   102  	ppc64.ABLT & obj.AMask: {Flags: gc.Cjmp},
   103  	ppc64.ABGT & obj.AMask: {Flags: gc.Cjmp},
   104  	ppc64.ABLE & obj.AMask: {Flags: gc.Cjmp},
   105  	obj.ARET:               {Flags: gc.Break},
   106  	obj.ADUFFZERO:          {Flags: gc.Call},
   107  	obj.ADUFFCOPY:          {Flags: gc.Call},
   108  }
   109  
   110  func initproginfo() {
   111  	var addvariant = []int{V_CC, V_V, V_CC | V_V}
   112  
   113  	// Perform one-time expansion of instructions in progtable to
   114  	// their CC, V, and VCC variants
   115  	for i := range progtable {
   116  		as := obj.As(i)
   117  		if progtable[as].Flags == 0 {
   118  			continue
   119  		}
   120  		variant := as2variant(as)
   121  		for i := range addvariant {
   122  			as2 := variant2as(as, variant|addvariant[i])
   123  			if as2 != 0 && progtable[as2&obj.AMask].Flags == 0 {
   124  				progtable[as2&obj.AMask] = progtable[as]
   125  			}
   126  		}
   127  	}
   128  }
   129  
   130  func proginfo(p *obj.Prog) {
   131  	info := &p.Info
   132  	*info = progtable[p.As&obj.AMask]
   133  	if info.Flags == 0 {
   134  		gc.Fatalf("proginfo: unknown instruction %v", p)
   135  	}
   136  
   137  	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
   138  		info.Flags &^= gc.RegRead
   139  		info.Flags |= gc.RightRead /*CanRegRead |*/
   140  	}
   141  
   142  	if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
   143  		info.Regindex |= RtoB(int(p.From.Reg))
   144  		if info.Flags&gc.PostInc != 0 {
   145  			info.Regset |= RtoB(int(p.From.Reg))
   146  		}
   147  	}
   148  
   149  	if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
   150  		info.Regindex |= RtoB(int(p.To.Reg))
   151  		if info.Flags&gc.PostInc != 0 {
   152  			info.Regset |= RtoB(int(p.To.Reg))
   153  		}
   154  	}
   155  
   156  	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
   157  		info.Flags &^= gc.LeftRead
   158  		info.Flags |= gc.LeftAddr
   159  	}
   160  
   161  	if p.As == obj.ADUFFZERO {
   162  		info.Reguse |= 1<<0 | RtoB(ppc64.REG_R3)
   163  		info.Regset |= RtoB(ppc64.REG_R3)
   164  	}
   165  
   166  	if p.As == obj.ADUFFCOPY {
   167  		// TODO(austin) Revisit when duffcopy is implemented
   168  		info.Reguse |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4) | RtoB(ppc64.REG_R5)
   169  
   170  		info.Regset |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4)
   171  	}
   172  }
   173  
   174  // Instruction variants table, populated by initvariants via Main.
   175  // The index is the base form of the instruction, masked by obj.AMask.
   176  // The 4 values are the unmasked base form, then the unmasked CC, V,
   177  // and VCC variants, respectively.
   178  var varianttable = [ppc64.ALAST & obj.AMask][4]obj.As{}
   179  
   180  func initvariant(as obj.As, variants ...obj.As) {
   181  	vv := &varianttable[as&obj.AMask]
   182  	vv[0] = as
   183  	for i, v := range variants {
   184  		vv[i+1] = v
   185  	}
   186  }
   187  
   188  func initvariants() {
   189  	initvariant(ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC)
   190  	initvariant(ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC)
   191  	initvariant(ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC)
   192  	initvariant(ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC)
   193  	initvariant(ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC)
   194  	initvariant(ppc64.AAND, ppc64.AANDCC)
   195  	initvariant(ppc64.AANDN, ppc64.AANDNCC)
   196  	initvariant(ppc64.ACNTLZD, ppc64.ACNTLZDCC)
   197  	initvariant(ppc64.ACNTLZW, ppc64.ACNTLZWCC)
   198  	initvariant(ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC)
   199  	initvariant(ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC)
   200  	initvariant(ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC)
   201  	initvariant(ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC)
   202  	initvariant(ppc64.AEQV, ppc64.AEQVCC)
   203  	initvariant(ppc64.AEXTSB, ppc64.AEXTSBCC)
   204  	initvariant(ppc64.AEXTSH, ppc64.AEXTSHCC)
   205  	initvariant(ppc64.AEXTSW, ppc64.AEXTSWCC)
   206  	initvariant(ppc64.AFABS, ppc64.AFABSCC)
   207  	initvariant(ppc64.AFADD, ppc64.AFADDCC)
   208  	initvariant(ppc64.AFADDS, ppc64.AFADDSCC)
   209  	initvariant(ppc64.AFCFID, ppc64.AFCFIDCC)
   210  	initvariant(ppc64.AFCFIDU, ppc64.AFCFIDUCC)
   211  	initvariant(ppc64.AFCTID, ppc64.AFCTIDCC)
   212  	initvariant(ppc64.AFCTIDZ, ppc64.AFCTIDZCC)
   213  	initvariant(ppc64.AFCTIW, ppc64.AFCTIWCC)
   214  	initvariant(ppc64.AFCTIWZ, ppc64.AFCTIWZCC)
   215  	initvariant(ppc64.AFDIV, ppc64.AFDIVCC)
   216  	initvariant(ppc64.AFDIVS, ppc64.AFDIVSCC)
   217  	initvariant(ppc64.AFMADD, ppc64.AFMADDCC)
   218  	initvariant(ppc64.AFMADDS, ppc64.AFMADDSCC)
   219  	initvariant(ppc64.AFMOVD, ppc64.AFMOVDCC)
   220  	initvariant(ppc64.AFMSUB, ppc64.AFMSUBCC)
   221  	initvariant(ppc64.AFMSUBS, ppc64.AFMSUBSCC)
   222  	initvariant(ppc64.AFMUL, ppc64.AFMULCC)
   223  	initvariant(ppc64.AFMULS, ppc64.AFMULSCC)
   224  	initvariant(ppc64.AFNABS, ppc64.AFNABSCC)
   225  	initvariant(ppc64.AFNEG, ppc64.AFNEGCC)
   226  	initvariant(ppc64.AFNMADD, ppc64.AFNMADDCC)
   227  	initvariant(ppc64.AFNMADDS, ppc64.AFNMADDSCC)
   228  	initvariant(ppc64.AFNMSUB, ppc64.AFNMSUBCC)
   229  	initvariant(ppc64.AFNMSUBS, ppc64.AFNMSUBSCC)
   230  	initvariant(ppc64.AFRES, ppc64.AFRESCC)
   231  	initvariant(ppc64.AFRSP, ppc64.AFRSPCC)
   232  	initvariant(ppc64.AFRSQRTE, ppc64.AFRSQRTECC)
   233  	initvariant(ppc64.AFSEL, ppc64.AFSELCC)
   234  	initvariant(ppc64.AFSQRT, ppc64.AFSQRTCC)
   235  	initvariant(ppc64.AFSQRTS, ppc64.AFSQRTSCC)
   236  	initvariant(ppc64.AFSUB, ppc64.AFSUBCC)
   237  	initvariant(ppc64.AFSUBS, ppc64.AFSUBSCC)
   238  	initvariant(ppc64.AMTFSB0, ppc64.AMTFSB0CC)
   239  	initvariant(ppc64.AMTFSB1, ppc64.AMTFSB1CC)
   240  	initvariant(ppc64.AMULHD, ppc64.AMULHDCC)
   241  	initvariant(ppc64.AMULHDU, ppc64.AMULHDUCC)
   242  	initvariant(ppc64.AMULHW, ppc64.AMULHWCC)
   243  	initvariant(ppc64.AMULHWU, ppc64.AMULHWUCC)
   244  	initvariant(ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC)
   245  	initvariant(ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC)
   246  	initvariant(ppc64.ANAND, ppc64.ANANDCC)
   247  	initvariant(ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC)
   248  	initvariant(ppc64.ANOR, ppc64.ANORCC)
   249  	initvariant(ppc64.AOR, ppc64.AORCC)
   250  	initvariant(ppc64.AORN, ppc64.AORNCC)
   251  	initvariant(ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC)
   252  	initvariant(ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC)
   253  	initvariant(ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC)
   254  	initvariant(ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC)
   255  	initvariant(ppc64.ARLDC, ppc64.ARLDCCC)
   256  	initvariant(ppc64.ARLDCL, ppc64.ARLDCLCC)
   257  	initvariant(ppc64.ARLDCR, ppc64.ARLDCRCC)
   258  	initvariant(ppc64.ARLDMI, ppc64.ARLDMICC)
   259  	initvariant(ppc64.ARLWMI, ppc64.ARLWMICC)
   260  	initvariant(ppc64.ARLWNM, ppc64.ARLWNMCC)
   261  	initvariant(ppc64.ASLD, ppc64.ASLDCC)
   262  	initvariant(ppc64.ASLW, ppc64.ASLWCC)
   263  	initvariant(ppc64.ASRAD, ppc64.ASRADCC)
   264  	initvariant(ppc64.ASRAW, ppc64.ASRAWCC)
   265  	initvariant(ppc64.ASRD, ppc64.ASRDCC)
   266  	initvariant(ppc64.ASRW, ppc64.ASRWCC)
   267  	initvariant(ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC)
   268  	initvariant(ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC)
   269  	initvariant(ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC)
   270  	initvariant(ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC)
   271  	initvariant(ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC)
   272  	initvariant(ppc64.AXOR, ppc64.AXORCC)
   273  
   274  	for i := range varianttable {
   275  		vv := &varianttable[i]
   276  		if vv[0] == 0 {
   277  			// Instruction has no variants
   278  			varianttable[i][0] = obj.As(i)
   279  			continue
   280  		}
   281  
   282  		// Copy base form to other variants
   283  		if vv[0]&obj.AMask == obj.As(i) {
   284  			for _, v := range vv {
   285  				if v != 0 {
   286  					varianttable[v&obj.AMask] = varianttable[i]
   287  				}
   288  			}
   289  		}
   290  	}
   291  }
   292  
   293  // as2variant returns the variant (V_*) flags of instruction as.
   294  func as2variant(as obj.As) int {
   295  	for i, v := range varianttable[as&obj.AMask] {
   296  		if v&obj.AMask == as&obj.AMask {
   297  			return i
   298  		}
   299  	}
   300  	gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as&obj.AMask))
   301  	return 0
   302  }
   303  
   304  // variant2as returns the instruction as with the given variant (V_*) flags.
   305  // If no such variant exists, this returns 0.
   306  func variant2as(as obj.As, flags int) obj.As {
   307  	return varianttable[as&obj.AMask][flags]
   308  }