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