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