github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5a/a.y (about)

     1  // Inferno utils/5a/a.y
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5a/a.y
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.	All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  %{
    32  #include <u.h>
    33  #include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
    34  #include <libc.h>
    35  #include "a.h"
    36  %}
    37  %union
    38  {
    39  	Sym	*sym;
    40  	int32	lval;
    41  	double	dval;
    42  	char	sval[8];
    43  	Gen	gen;
    44  }
    45  %left	'|'
    46  %left	'^'
    47  %left	'&'
    48  %left	'<' '>'
    49  %left	'+' '-'
    50  %left	'*' '/' '%'
    51  %token	<lval>	LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
    52  %token	<lval>	LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
    53  %token	<lval>	LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
    54  %token	<lval>	LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
    55  %token	<lval>	LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
    56  %token	<lval>	LCONST LSP LSB LFP LPC
    57  %token	<lval>	LTYPEX LR LREG LF LFREG LC LCREG LPSR LFCR
    58  %token	<lval>	LCOND LS LAT
    59  %token	<dval>	LFCONST
    60  %token	<sval>	LSCONST
    61  %token	<sym>	LNAME LLAB LVAR
    62  %type	<lval>	con expr oexpr pointer offset sreg spreg creg
    63  %type	<lval>	rcon cond reglist
    64  %type	<gen>	gen rel reg regreg freg shift fcon frcon
    65  %type	<gen>	imm ximm name oreg ireg nireg ioreg imsr
    66  %%
    67  prog:
    68  |	prog
    69  	{
    70  		stmtline = lineno;
    71  	}
    72  	line
    73  
    74  line:
    75  	LLAB ':'
    76  	{
    77  		if($1->value != pc)
    78  			yyerror("redeclaration of %s", $1->name);
    79  		$1->value = pc;
    80  	}
    81  	line
    82  |	LNAME ':'
    83  	{
    84  		$1->type = LLAB;
    85  		$1->value = pc;
    86  	}
    87  	line
    88  |	LNAME '=' expr ';'
    89  	{
    90  		$1->type = LVAR;
    91  		$1->value = $3;
    92  	}
    93  |	LVAR '=' expr ';'
    94  	{
    95  		if($1->value != $3)
    96  			yyerror("redeclaration of %s", $1->name);
    97  		$1->value = $3;
    98  	}
    99  |	';'
   100  |	inst ';'
   101  |	error ';'
   102  
   103  inst:
   104  /*
   105   * ADD
   106   */
   107  	LTYPE1 cond imsr ',' spreg ',' reg
   108  	{
   109  		outcode($1, $2, &$3, $5, &$7);
   110  	}
   111  |	LTYPE1 cond imsr ',' spreg ','
   112  	{
   113  		outcode($1, $2, &$3, $5, &nullgen);
   114  	}
   115  |	LTYPE1 cond imsr ',' reg
   116  	{
   117  		outcode($1, $2, &$3, NREG, &$5);
   118  	}
   119  /*
   120   * MVN
   121   */
   122  |	LTYPE2 cond imsr ',' reg
   123  	{
   124  		outcode($1, $2, &$3, NREG, &$5);
   125  	}
   126  /*
   127   * MOVW
   128   */
   129  |	LTYPE3 cond gen ',' gen
   130  	{
   131  		outcode($1, $2, &$3, NREG, &$5);
   132  	}
   133  /*
   134   * B/BL
   135   */
   136  |	LTYPE4 cond comma rel
   137  	{
   138  		outcode($1, $2, &nullgen, NREG, &$4);
   139  	}
   140  |	LTYPE4 cond comma nireg
   141  	{
   142  		outcode($1, $2, &nullgen, NREG, &$4);
   143  	}
   144  /*
   145   * BX
   146   */
   147  |	LTYPEBX comma ireg
   148  	{
   149  		outcode($1, Always, &nullgen, NREG, &$3);
   150  	}
   151  /*
   152   * BEQ
   153   */
   154  |	LTYPE5 comma rel
   155  	{
   156  		outcode($1, Always, &nullgen, NREG, &$3);
   157  	}
   158  /*
   159   * SWI
   160   */
   161  |	LTYPE6 cond comma gen
   162  	{
   163  		outcode($1, $2, &nullgen, NREG, &$4);
   164  	}
   165  /*
   166   * CMP
   167   */
   168  |	LTYPE7 cond imsr ',' spreg comma
   169  	{
   170  		outcode($1, $2, &$3, $5, &nullgen);
   171  	}
   172  /*
   173   * MOVM
   174   */
   175  |	LTYPE8 cond ioreg ',' '[' reglist ']'
   176  	{
   177  		Gen g;
   178  
   179  		g = nullgen;
   180  		g.type = D_CONST;
   181  		g.offset = $6;
   182  		outcode($1, $2, &$3, NREG, &g);
   183  	}
   184  |	LTYPE8 cond '[' reglist ']' ',' ioreg
   185  	{
   186  		Gen g;
   187  
   188  		g = nullgen;
   189  		g.type = D_CONST;
   190  		g.offset = $4;
   191  		outcode($1, $2, &g, NREG, &$7);
   192  	}
   193  /*
   194   * SWAP
   195   */
   196  |	LTYPE9 cond reg ',' ireg ',' reg
   197  	{
   198  		outcode($1, $2, &$5, $3.reg, &$7);
   199  	}
   200  |	LTYPE9 cond reg ',' ireg comma
   201  	{
   202  		outcode($1, $2, &$5, $3.reg, &$3);
   203  	}
   204  |	LTYPE9 cond comma ireg ',' reg
   205  	{
   206  		outcode($1, $2, &$4, $6.reg, &$6);
   207  	}
   208  /*
   209   * RET
   210   */
   211  |	LTYPEA cond comma
   212  	{
   213  		outcode($1, $2, &nullgen, NREG, &nullgen);
   214  	}
   215  /*
   216   * TEXT/GLOBL
   217   */
   218  |	LTYPEB name ',' imm
   219  	{
   220  		outcode($1, Always, &$2, 0, &$4);
   221  	}
   222  |	LTYPEB name ',' con ',' imm
   223  	{
   224  		outcode($1, Always, &$2, $4, &$6);
   225  	}
   226  /*
   227   * DATA
   228   */
   229  |	LTYPEC name '/' con ',' ximm
   230  	{
   231  		outcode($1, Always, &$2, $4, &$6);
   232  	}
   233  /*
   234   * CASE
   235   */
   236  |	LTYPED cond reg comma
   237  	{
   238  		outcode($1, $2, &$3, NREG, &nullgen);
   239  	}
   240  /*
   241   * word
   242   */
   243  |	LTYPEH comma ximm
   244  	{
   245  		outcode($1, Always, &nullgen, NREG, &$3);
   246  	}
   247  /*
   248   * floating-point coprocessor
   249   */
   250  |	LTYPEI cond freg ',' freg
   251  	{
   252  		outcode($1, $2, &$3, NREG, &$5);
   253  	}
   254  |	LTYPEK cond frcon ',' freg
   255  	{
   256  		outcode($1, $2, &$3, NREG, &$5);
   257  	}
   258  |	LTYPEK cond frcon ',' LFREG ',' freg
   259  	{
   260  		outcode($1, $2, &$3, $5, &$7);
   261  	}
   262  |	LTYPEL cond freg ',' freg comma
   263  	{
   264  		outcode($1, $2, &$3, $5.reg, &nullgen);
   265  	}
   266  /*
   267   * MCR MRC
   268   */
   269  |	LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
   270  	{
   271  		Gen g;
   272  
   273  		g = nullgen;
   274  		g.type = D_CONST;
   275  		g.offset =
   276  			(0xe << 24) |		/* opcode */
   277  			($1 << 20) |		/* MCR/MRC */
   278  			($2 << 28) |		/* scond */
   279  			(($3 & 15) << 8) |	/* coprocessor number */
   280  			(($5 & 7) << 21) |	/* coprocessor operation */
   281  			(($7 & 15) << 12) |	/* arm register */
   282  			(($9 & 15) << 16) |	/* Crn */
   283  			(($11 & 15) << 0) |	/* Crm */
   284  			(($12 & 7) << 5) |	/* coprocessor information */
   285  			(1<<4);			/* must be set */
   286  		outcode(AWORD, Always, &nullgen, NREG, &g);
   287  	}
   288  /*
   289   * MULL r1,r2,(hi,lo)
   290   */
   291  |	LTYPEM cond reg ',' reg ',' regreg
   292  	{
   293  		outcode($1, $2, &$3, $5.reg, &$7);
   294  	}
   295  /*
   296   * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
   297   * MULAW{T,B} r1,r2,r3,r4
   298   */
   299  |	LTYPEN cond reg ',' reg ',' reg ',' spreg
   300  	{
   301  		$7.type = D_REGREG2;
   302  		$7.offset = $9;
   303  		outcode($1, $2, &$3, $5.reg, &$7);
   304  	}
   305  /*
   306   * PLD
   307   */
   308  |	LTYPEPLD oreg
   309  	{
   310  		outcode($1, Always, &$2, NREG, &nullgen);
   311  	}
   312  /*
   313   * END
   314   */
   315  |	LTYPEE comma
   316  	{
   317  		outcode($1, Always, &nullgen, NREG, &nullgen);
   318  	}
   319  
   320  cond:
   321  	{
   322  		$$ = Always;
   323  	}
   324  |	cond LCOND
   325  	{
   326  		$$ = ($1 & ~C_SCOND) | $2;
   327  	}
   328  |	cond LS
   329  	{
   330  		$$ = $1 | $2;
   331  	}
   332  
   333  comma:
   334  |	',' comma
   335  
   336  rel:
   337  	con '(' LPC ')'
   338  	{
   339  		$$ = nullgen;
   340  		$$.type = D_BRANCH;
   341  		$$.offset = $1 + pc;
   342  	}
   343  |	LNAME offset
   344  	{
   345  		$$ = nullgen;
   346  		if(pass == 2)
   347  			yyerror("undefined label: %s", $1->name);
   348  		$$.type = D_BRANCH;
   349  		$$.sym = $1;
   350  		$$.offset = $2;
   351  	}
   352  |	LLAB offset
   353  	{
   354  		$$ = nullgen;
   355  		$$.type = D_BRANCH;
   356  		$$.sym = $1;
   357  		$$.offset = $1->value + $2;
   358  	}
   359  
   360  ximm:	'$' con
   361  	{
   362  		$$ = nullgen;
   363  		$$.type = D_CONST;
   364  		$$.offset = $2;
   365  	}
   366  |	'$' oreg
   367  	{
   368  		$$ = $2;
   369  		$$.type = D_CONST;
   370  	}
   371  |	'$' '*' '$' oreg
   372  	{
   373  		$$ = $4;
   374  		$$.type = D_OCONST;
   375  	}
   376  |	'$' LSCONST
   377  	{
   378  		$$ = nullgen;
   379  		$$.type = D_SCONST;
   380  		memcpy($$.sval, $2, sizeof($$.sval));
   381  	}
   382  |	fcon
   383  
   384  fcon:
   385  	'$' LFCONST
   386  	{
   387  		$$ = nullgen;
   388  		$$.type = D_FCONST;
   389  		$$.dval = $2;
   390  	}
   391  |	'$' '-' LFCONST
   392  	{
   393  		$$ = nullgen;
   394  		$$.type = D_FCONST;
   395  		$$.dval = -$3;
   396  	}
   397  
   398  reglist:
   399  	spreg
   400  	{
   401  		$$ = 1 << $1;
   402  	}
   403  |	spreg '-' spreg
   404  	{
   405  		int i;
   406  		$$=0;
   407  		for(i=$1; i<=$3; i++)
   408  			$$ |= 1<<i;
   409  		for(i=$3; i<=$1; i++)
   410  			$$ |= 1<<i;
   411  	}
   412  |	spreg comma reglist
   413  	{
   414  		$$ = (1<<$1) | $3;
   415  	}
   416  
   417  gen:
   418  	reg
   419  |	ximm
   420  |	shift
   421  |	shift '(' spreg ')'
   422  	{
   423  		$$ = $1;
   424  		$$.reg = $3;
   425  	}
   426  |	LPSR
   427  	{
   428  		$$ = nullgen;
   429  		$$.type = D_PSR;
   430  		$$.reg = $1;
   431  	}
   432  |	LFCR
   433  	{
   434  		$$ = nullgen;
   435  		$$.type = D_FPCR;
   436  		$$.reg = $1;
   437  	}
   438  |	con
   439  	{
   440  		$$ = nullgen;
   441  		$$.type = D_OREG;
   442  		$$.offset = $1;
   443  	}
   444  |	oreg
   445  |	freg
   446  
   447  nireg:
   448  	ireg
   449  |	name
   450  	{
   451  		$$ = $1;
   452  		if($1.name != D_EXTERN && $1.name != D_STATIC) {
   453  		}
   454  	}
   455  
   456  ireg:
   457  	'(' spreg ')'
   458  	{
   459  		$$ = nullgen;
   460  		$$.type = D_OREG;
   461  		$$.reg = $2;
   462  		$$.offset = 0;
   463  	}
   464  
   465  ioreg:
   466  	ireg
   467  |	con '(' sreg ')'
   468  	{
   469  		$$ = nullgen;
   470  		$$.type = D_OREG;
   471  		$$.reg = $3;
   472  		$$.offset = $1;
   473  	}
   474  
   475  oreg:
   476  	name
   477  |	name '(' sreg ')'
   478  	{
   479  		$$ = $1;
   480  		$$.type = D_OREG;
   481  		$$.reg = $3;
   482  	}
   483  |	ioreg
   484  
   485  imsr:
   486  	reg
   487  |	imm
   488  |	shift
   489  
   490  imm:	'$' con
   491  	{
   492  		$$ = nullgen;
   493  		$$.type = D_CONST;
   494  		$$.offset = $2;
   495  	}
   496  
   497  reg:
   498  	spreg
   499  	{
   500  		$$ = nullgen;
   501  		$$.type = D_REG;
   502  		$$.reg = $1;
   503  	}
   504  
   505  regreg:
   506  	'(' spreg ',' spreg ')'
   507  	{
   508  		$$ = nullgen;
   509  		$$.type = D_REGREG;
   510  		$$.reg = $2;
   511  		$$.offset = $4;
   512  	}
   513  
   514  shift:
   515  	spreg '<' '<' rcon
   516  	{
   517  		$$ = nullgen;
   518  		$$.type = D_SHIFT;
   519  		$$.offset = $1 | $4 | (0 << 5);
   520  	}
   521  |	spreg '>' '>' rcon
   522  	{
   523  		$$ = nullgen;
   524  		$$.type = D_SHIFT;
   525  		$$.offset = $1 | $4 | (1 << 5);
   526  	}
   527  |	spreg '-' '>' rcon
   528  	{
   529  		$$ = nullgen;
   530  		$$.type = D_SHIFT;
   531  		$$.offset = $1 | $4 | (2 << 5);
   532  	}
   533  |	spreg LAT '>' rcon
   534  	{
   535  		$$ = nullgen;
   536  		$$.type = D_SHIFT;
   537  		$$.offset = $1 | $4 | (3 << 5);
   538  	}
   539  
   540  rcon:
   541  	spreg
   542  	{
   543  		if($$ < 0 || $$ >= 16)
   544  			print("register value out of range\n");
   545  		$$ = (($1&15) << 8) | (1 << 4);
   546  	}
   547  |	con
   548  	{
   549  		if($$ < 0 || $$ >= 32)
   550  			print("shift value out of range\n");
   551  		$$ = ($1&31) << 7;
   552  	}
   553  
   554  sreg:
   555  	LREG
   556  |	LPC
   557  	{
   558  		$$ = REGPC;
   559  	}
   560  |	LR '(' expr ')'
   561  	{
   562  		if($3 < 0 || $3 >= NREG)
   563  			print("register value out of range\n");
   564  		$$ = $3;
   565  	}
   566  
   567  spreg:
   568  	sreg
   569  |	LSP
   570  	{
   571  		$$ = REGSP;
   572  	}
   573  
   574  creg:
   575  	LCREG
   576  |	LC '(' expr ')'
   577  	{
   578  		if($3 < 0 || $3 >= NREG)
   579  			print("register value out of range\n");
   580  		$$ = $3;
   581  	}
   582  
   583  frcon:
   584  	freg
   585  |	fcon
   586  
   587  freg:
   588  	LFREG
   589  	{
   590  		$$ = nullgen;
   591  		$$.type = D_FREG;
   592  		$$.reg = $1;
   593  	}
   594  |	LF '(' con ')'
   595  	{
   596  		$$ = nullgen;
   597  		$$.type = D_FREG;
   598  		$$.reg = $3;
   599  	}
   600  
   601  name:
   602  	con '(' pointer ')'
   603  	{
   604  		$$ = nullgen;
   605  		$$.type = D_OREG;
   606  		$$.name = $3;
   607  		$$.sym = S;
   608  		$$.offset = $1;
   609  	}
   610  |	LNAME offset '(' pointer ')'
   611  	{
   612  		$$ = nullgen;
   613  		$$.type = D_OREG;
   614  		$$.name = $4;
   615  		$$.sym = $1;
   616  		$$.offset = $2;
   617  	}
   618  |	LNAME '<' '>' offset '(' LSB ')'
   619  	{
   620  		$$ = nullgen;
   621  		$$.type = D_OREG;
   622  		$$.name = D_STATIC;
   623  		$$.sym = $1;
   624  		$$.offset = $4;
   625  	}
   626  
   627  offset:
   628  	{
   629  		$$ = 0;
   630  	}
   631  |	'+' con
   632  	{
   633  		$$ = $2;
   634  	}
   635  |	'-' con
   636  	{
   637  		$$ = -$2;
   638  	}
   639  
   640  pointer:
   641  	LSB
   642  |	LSP
   643  |	LFP
   644  
   645  con:
   646  	LCONST
   647  |	LVAR
   648  	{
   649  		$$ = $1->value;
   650  	}
   651  |	'-' con
   652  	{
   653  		$$ = -$2;
   654  	}
   655  |	'+' con
   656  	{
   657  		$$ = $2;
   658  	}
   659  |	'~' con
   660  	{
   661  		$$ = ~$2;
   662  	}
   663  |	'(' expr ')'
   664  	{
   665  		$$ = $2;
   666  	}
   667  
   668  oexpr:
   669  	{
   670  		$$ = 0;
   671  	}
   672  |	',' expr
   673  	{
   674  		$$ = $2;
   675  	}
   676  
   677  expr:
   678  	con
   679  |	expr '+' expr
   680  	{
   681  		$$ = $1 + $3;
   682  	}
   683  |	expr '-' expr
   684  	{
   685  		$$ = $1 - $3;
   686  	}
   687  |	expr '*' expr
   688  	{
   689  		$$ = $1 * $3;
   690  	}
   691  |	expr '/' expr
   692  	{
   693  		$$ = $1 / $3;
   694  	}
   695  |	expr '%' expr
   696  	{
   697  		$$ = $1 % $3;
   698  	}
   699  |	expr '<' '<' expr
   700  	{
   701  		$$ = $1 << $4;
   702  	}
   703  |	expr '>' '>' expr
   704  	{
   705  		$$ = $1 >> $4;
   706  	}
   707  |	expr '&' expr
   708  	{
   709  		$$ = $1 & $3;
   710  	}
   711  |	expr '^' expr
   712  	{
   713  		$$ = $1 ^ $3;
   714  	}
   715  |	expr '|' expr
   716  	{
   717  		$$ = $1 | $3;
   718  	}