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