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