github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/8a/a.y (about)

     1  // Inferno utils/8a/a.y
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8a/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  #include "../../runtime/funcdata.h"
    37  %}
    38  %union	{
    39  	Sym	*sym;
    40  	int32	lval;
    41  	struct {
    42  		int32 v1;
    43  		int32 v2;
    44  	} con2;
    45  	double	dval;
    46  	char	sval[8];
    47  	Addr	addr;
    48  	Addr2	addr2;
    49  }
    50  %left	'|'
    51  %left	'^'
    52  %left	'&'
    53  %left	'<' '>'
    54  %left	'+' '-'
    55  %left	'*' '/' '%'
    56  %token	<lval>	LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
    57  %token	<lval>	LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
    58  %token	<lval>	LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB
    59  %token	<lval>	LBREG LLREG LSREG LFREG LXREG
    60  %token	<dval>	LFCONST
    61  %token	<sval>	LSCONST LSP
    62  %token	<sym>	LNAME LLAB LVAR
    63  %type	<lval>	con expr pointer offset
    64  %type	<con2>	con2
    65  %type	<addr>	mem imm imm2 reg nam rel rem rim rom omem nmem
    66  %type	<addr2>	nonnon nonrel nonrem rimnon rimrem remrim
    67  %type	<addr2>	spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12
    68  %%
    69  prog:
    70  |	prog
    71  	{
    72  		stmtline = lineno;
    73  	}
    74  	line
    75  
    76  line:
    77  	LNAME ':'
    78  	{
    79  		$1 = labellookup($1);
    80  		if($1->type == LLAB && $1->value != pc)
    81  			yyerror("redeclaration of %s", $1->labelname);
    82  		$1->type = LLAB;
    83  		$1->value = pc;
    84  	}
    85  	line
    86  |	';'
    87  |	inst ';'
    88  |	error ';'
    89  
    90  inst:
    91  	LNAME '=' expr
    92  	{
    93  		$1->type = LVAR;
    94  		$1->value = $3;
    95  	}
    96  |	LVAR '=' expr
    97  	{
    98  		if($1->value != $3)
    99  			yyerror("redeclaration of %s", $1->name);
   100  		$1->value = $3;
   101  	}
   102  |	LTYPE0 nonnon	{ outcode($1, &$2); }
   103  |	LTYPE1 nonrem	{ outcode($1, &$2); }
   104  |	LTYPE2 rimnon	{ outcode($1, &$2); }
   105  |	LTYPE3 rimrem	{ outcode($1, &$2); }
   106  |	LTYPE4 remrim	{ outcode($1, &$2); }
   107  |	LTYPER nonrel	{ outcode($1, &$2); }
   108  |	LTYPED spec1	{ outcode($1, &$2); }
   109  |	LTYPET spec2	{ outcode($1, &$2); }
   110  |	LTYPEC spec3	{ outcode($1, &$2); }
   111  |	LTYPEN spec4	{ outcode($1, &$2); }
   112  |	LTYPES spec5	{ outcode($1, &$2); }
   113  |	LTYPEM spec6	{ outcode($1, &$2); }
   114  |	LTYPEI spec7	{ outcode($1, &$2); }
   115  |	LTYPEG spec8	{ outcode($1, &$2); }
   116  |	LTYPEXC spec9	{ outcode($1, &$2); }
   117  |	LTYPEX spec10	{ outcode($1, &$2); }
   118  |	LTYPEPC spec11	{ outcode($1, &$2); }
   119  |	LTYPEF spec12	{ outcode($1, &$2); }
   120  
   121  nonnon:
   122  	{
   123  		$$.from = nullgen;
   124  		$$.to = nullgen;
   125  	}
   126  |	','
   127  	{
   128  		$$.from = nullgen;
   129  		$$.to = nullgen;
   130  	}
   131  
   132  rimrem:
   133  	rim ',' rem
   134  	{
   135  		$$.from = $1;
   136  		$$.to = $3;
   137  	}
   138  
   139  remrim:
   140  	rem ',' rim
   141  	{
   142  		$$.from = $1;
   143  		$$.to = $3;
   144  	}
   145  
   146  rimnon:
   147  	rim ','
   148  	{
   149  		$$.from = $1;
   150  		$$.to = nullgen;
   151  	}
   152  |	rim
   153  	{
   154  		$$.from = $1;
   155  		$$.to = nullgen;
   156  	}
   157  
   158  nonrem:
   159  	',' rem
   160  	{
   161  		$$.from = nullgen;
   162  		$$.to = $2;
   163  	}
   164  |	rem
   165  	{
   166  		$$.from = nullgen;
   167  		$$.to = $1;
   168  	}
   169  
   170  nonrel:
   171  	',' rel
   172  	{
   173  		$$.from = nullgen;
   174  		$$.to = $2;
   175  	}
   176  |	rel
   177  	{
   178  		$$.from = nullgen;
   179  		$$.to = $1;
   180  	}
   181  |	imm ',' rel
   182  	{
   183  		$$.from = $1;
   184  		$$.to = $3;
   185  	}
   186  
   187  spec1:	/* DATA */
   188  	nam '/' con ',' imm
   189  	{
   190  		$$.from = $1;
   191  		$$.from.scale = $3;
   192  		$$.to = $5;
   193  	}
   194  
   195  spec2:	/* TEXT */
   196  	mem ',' imm2
   197  	{
   198  		settext($1.sym);
   199  		$$.from = $1;
   200  		$$.to = $3;
   201  	}
   202  |	mem ',' con ',' imm2
   203  	{
   204  		settext($1.sym);
   205  		$$.from = $1;
   206  		$$.from.scale = $3;
   207  		$$.to = $5;
   208  	}
   209  
   210  spec3:	/* JMP/CALL */
   211  	',' rom
   212  	{
   213  		$$.from = nullgen;
   214  		$$.to = $2;
   215  	}
   216  |	rom
   217  	{
   218  		$$.from = nullgen;
   219  		$$.to = $1;
   220  	}
   221  |	'*' nam
   222  	{
   223  		$$.from = nullgen;
   224  		$$.to = $2;
   225  		$$.to.index = $2.type;
   226  		$$.to.type = D_INDIR+D_ADDR;
   227  	}
   228  
   229  spec4:	/* NOP */
   230  	nonnon
   231  |	nonrem
   232  
   233  spec5:	/* SHL/SHR */
   234  	rim ',' rem
   235  	{
   236  		$$.from = $1;
   237  		$$.to = $3;
   238  	}
   239  |	rim ',' rem ':' LLREG
   240  	{
   241  		$$.from = $1;
   242  		$$.to = $3;
   243  		if($$.from.index != D_NONE)
   244  			yyerror("dp shift with lhs index");
   245  		$$.from.index = $5;
   246  	}
   247  
   248  spec6:	/* MOVW/MOVL */
   249  	rim ',' rem
   250  	{
   251  		$$.from = $1;
   252  		$$.to = $3;
   253  	}
   254  |	rim ',' rem ':' LSREG
   255  	{
   256  		$$.from = $1;
   257  		$$.to = $3;
   258  		if($$.to.index != D_NONE)
   259  			yyerror("dp move with lhs index");
   260  		$$.to.index = $5;
   261  	}
   262  
   263  spec7:
   264  	rim ','
   265  	{
   266  		$$.from = $1;
   267  		$$.to = nullgen;
   268  	}
   269  |	rim
   270  	{
   271  		$$.from = $1;
   272  		$$.to = nullgen;
   273  	}
   274  |	rim ',' rem
   275  	{
   276  		$$.from = $1;
   277  		$$.to = $3;
   278  	}
   279  
   280  spec8:	/* GLOBL */
   281  	mem ',' imm
   282  	{
   283  		$$.from = $1;
   284  		$$.to = $3;
   285  	}
   286  |	mem ',' con ',' imm
   287  	{
   288  		$$.from = $1;
   289  		$$.from.scale = $3;
   290  		$$.to = $5;
   291  	}
   292  
   293  spec9:	/* CMPPS/CMPPD */
   294  	reg ',' rem ',' con
   295  	{
   296  		$$.from = $1;
   297  		$$.to = $3;
   298  		$$.to.offset = $5;
   299  	}
   300  
   301  spec10:	/* PINSRD */
   302  	imm ',' rem ',' reg
   303  	{
   304  		$$.from = $3;
   305  		$$.to = $5;
   306  		if($1.type != D_CONST)
   307  			yyerror("illegal constant");
   308  		$$.to.offset = $1.offset;
   309  	}
   310  
   311  spec11:	/* PCDATA */
   312  	rim ',' rim
   313  	{
   314  		if($1.type != D_CONST || $3.type != D_CONST)
   315  			yyerror("arguments to PCDATA must be integer constants");
   316  		$$.from = $1;
   317  		$$.to = $3;
   318  	}
   319  
   320  spec12:	/* FUNCDATA */
   321  	rim ',' rim
   322  	{
   323  		if($1.type != D_CONST)
   324  			yyerror("index for FUNCDATA must be integer constant");
   325  		if($3.type != D_EXTERN && $3.type != D_STATIC)
   326  			yyerror("value for FUNCDATA must be symbol reference");
   327   		$$.from = $1;
   328   		$$.to = $3;
   329   	}
   330  
   331  rem:
   332  	reg
   333  |	mem
   334  
   335  rom:
   336  	rel
   337  |	nmem
   338  |	'*' reg
   339  	{
   340  		$$ = $2;
   341  	}
   342  |	'*' omem
   343  	{
   344  		$$ = $2;
   345  	}
   346  |	reg
   347  |	omem
   348  |	imm
   349  
   350  rim:
   351  	rem
   352  |	imm
   353  
   354  rel:
   355  	con '(' LPC ')'
   356  	{
   357  		$$ = nullgen;
   358  		$$.type = D_BRANCH;
   359  		$$.offset = $1 + pc;
   360  	}
   361  |	LNAME offset
   362  	{
   363  		$1 = labellookup($1);
   364  		$$ = nullgen;
   365  		if(pass == 2 && $1->type != LLAB)
   366  			yyerror("undefined label: %s", $1->labelname);
   367  		$$.type = D_BRANCH;
   368  		$$.offset = $1->value + $2;
   369  	}
   370  
   371  reg:
   372  	LBREG
   373  	{
   374  		$$ = nullgen;
   375  		$$.type = $1;
   376  	}
   377  |	LFREG
   378  	{
   379  		$$ = nullgen;
   380  		$$.type = $1;
   381  	}
   382  |	LLREG
   383  	{
   384  		$$ = nullgen;
   385  		$$.type = $1;
   386  	}
   387  |	LXREG
   388  	{
   389  		$$ = nullgen;
   390  		$$.type = $1;
   391  	}
   392  |	LSP
   393  	{
   394  		$$ = nullgen;
   395  		$$.type = D_SP;
   396  	}
   397  |	LSREG
   398  	{
   399  		$$ = nullgen;
   400  		$$.type = $1;
   401  	}
   402  
   403  imm:
   404  	'$' con
   405  	{
   406  		$$ = nullgen;
   407  		$$.type = D_CONST;
   408  		$$.offset = $2;
   409  	}
   410  |	'$' nam
   411  	{
   412  		$$ = $2;
   413  		$$.index = $2.type;
   414  		$$.type = D_ADDR;
   415  		/*
   416  		if($2.type == D_AUTO || $2.type == D_PARAM)
   417  			yyerror("constant cannot be automatic: %s",
   418  				$2.sym->name);
   419  		 */
   420  	}
   421  |	'$' LSCONST
   422  	{
   423  		$$ = nullgen;
   424  		$$.type = D_SCONST;
   425  		memcpy($$.u.sval, $2, sizeof($$.u.sval));
   426  	}
   427  |	'$' LFCONST
   428  	{
   429  		$$ = nullgen;
   430  		$$.type = D_FCONST;
   431  		$$.u.dval = $2;
   432  	}
   433  |	'$' '(' LFCONST ')'
   434  	{
   435  		$$ = nullgen;
   436  		$$.type = D_FCONST;
   437  		$$.u.dval = $3;
   438  	}
   439  |	'$' '(' '-' LFCONST ')'
   440  	{
   441  		$$ = nullgen;
   442  		$$.type = D_FCONST;
   443  		$$.u.dval = -$4;
   444  	}
   445  |	'$' '-' LFCONST
   446  	{
   447  		$$ = nullgen;
   448  		$$.type = D_FCONST;
   449  		$$.u.dval = -$3;
   450  	}
   451  
   452  imm2:
   453  	'$' con2
   454  	{
   455  		$$ = nullgen;
   456  		$$.type = D_CONST2;
   457  		$$.offset = $2.v1;
   458  		$$.offset2 = $2.v2;
   459  	}
   460  
   461  con2:
   462  	LCONST
   463  	{
   464  		$$.v1 = $1;
   465  		$$.v2 = ArgsSizeUnknown;
   466  	}
   467  |	'-' LCONST
   468  	{
   469  		$$.v1 = -$2;
   470  		$$.v2 = ArgsSizeUnknown;
   471  	}
   472  |	LCONST '-' LCONST
   473  	{
   474  		$$.v1 = $1;
   475  		$$.v2 = $3;
   476  	}
   477  |	'-' LCONST '-' LCONST
   478  	{
   479  		$$.v1 = -$2;
   480  		$$.v2 = $4;
   481  	}
   482  
   483  mem:
   484  	omem
   485  |	nmem
   486  
   487  omem:
   488  	con
   489  	{
   490  		$$ = nullgen;
   491  		$$.type = D_INDIR+D_NONE;
   492  		$$.offset = $1;
   493  	}
   494  |	con '(' LLREG ')'
   495  	{
   496  		$$ = nullgen;
   497  		$$.type = D_INDIR+$3;
   498  		$$.offset = $1;
   499  	}
   500  |	con '(' LSP ')'
   501  	{
   502  		$$ = nullgen;
   503  		$$.type = D_INDIR+D_SP;
   504  		$$.offset = $1;
   505  	}
   506  |	con '(' LLREG '*' con ')'
   507  	{
   508  		$$ = nullgen;
   509  		$$.type = D_INDIR+D_NONE;
   510  		$$.offset = $1;
   511  		$$.index = $3;
   512  		$$.scale = $5;
   513  		checkscale($$.scale);
   514  	}
   515  |	con '(' LLREG ')' '(' LLREG '*' con ')'
   516  	{
   517  		$$ = nullgen;
   518  		$$.type = D_INDIR+$3;
   519  		$$.offset = $1;
   520  		$$.index = $6;
   521  		$$.scale = $8;
   522  		checkscale($$.scale);
   523  	}
   524  |	con '(' LLREG ')' '(' LSREG '*' con ')'
   525  	{
   526  		$$ = nullgen;
   527  		$$.type = D_INDIR+$3;
   528  		$$.offset = $1;
   529  		$$.index = $6;
   530  		$$.scale = $8;
   531  		checkscale($$.scale);
   532  	}
   533  |	'(' LLREG ')'
   534  	{
   535  		$$ = nullgen;
   536  		$$.type = D_INDIR+$2;
   537  	}
   538  |	'(' LSP ')'
   539  	{
   540  		$$ = nullgen;
   541  		$$.type = D_INDIR+D_SP;
   542  	}
   543  |	con '(' LSREG ')'
   544  	{
   545  		$$ = nullgen;
   546  		$$.type = D_INDIR+$3;
   547  		$$.offset = $1;
   548  	}
   549  |	'(' LLREG '*' con ')'
   550  	{
   551  		$$ = nullgen;
   552  		$$.type = D_INDIR+D_NONE;
   553  		$$.index = $2;
   554  		$$.scale = $4;
   555  		checkscale($$.scale);
   556  	}
   557  |	'(' LLREG ')' '(' LLREG '*' con ')'
   558  	{
   559  		$$ = nullgen;
   560  		$$.type = D_INDIR+$2;
   561  		$$.index = $5;
   562  		$$.scale = $7;
   563  		checkscale($$.scale);
   564  	}
   565  
   566  nmem:
   567  	nam
   568  	{
   569  		$$ = $1;
   570  	}
   571  |	nam '(' LLREG '*' con ')'
   572  	{
   573  		$$ = $1;
   574  		$$.index = $3;
   575  		$$.scale = $5;
   576  		checkscale($$.scale);
   577  	}
   578  
   579  nam:
   580  	LNAME offset '(' pointer ')'
   581  	{
   582  		$$ = nullgen;
   583  		$$.type = $4;
   584  		$$.sym = linklookup(ctxt, $1->name, 0);
   585  		$$.offset = $2;
   586  	}
   587  |	LNAME '<' '>' offset '(' LSB ')'
   588  	{
   589  		$$ = nullgen;
   590  		$$.type = D_STATIC;
   591  		$$.sym = linklookup(ctxt, $1->name, 1);
   592  		$$.offset = $4;
   593  	}
   594  
   595  offset:
   596  	{
   597  		$$ = 0;
   598  	}
   599  |	'+' con
   600  	{
   601  		$$ = $2;
   602  	}
   603  |	'-' con
   604  	{
   605  		$$ = -$2;
   606  	}
   607  
   608  pointer:
   609  	LSB
   610  |	LSP
   611  	{
   612  		$$ = D_AUTO;
   613  	}
   614  |	LFP
   615  
   616  con:
   617  	LCONST
   618  |	LVAR
   619  	{
   620  		$$ = $1->value;
   621  	}
   622  |	'-' con
   623  	{
   624  		$$ = -$2;
   625  	}
   626  |	'+' con
   627  	{
   628  		$$ = $2;
   629  	}
   630  |	'~' con
   631  	{
   632  		$$ = ~$2;
   633  	}
   634  |	'(' expr ')'
   635  	{
   636  		$$ = $2;
   637  	}
   638  
   639  expr:
   640  	con
   641  |	expr '+' expr
   642  	{
   643  		$$ = $1 + $3;
   644  	}
   645  |	expr '-' expr
   646  	{
   647  		$$ = $1 - $3;
   648  	}
   649  |	expr '*' expr
   650  	{
   651  		$$ = $1 * $3;
   652  	}
   653  |	expr '/' expr
   654  	{
   655  		$$ = $1 / $3;
   656  	}
   657  |	expr '%' expr
   658  	{
   659  		$$ = $1 % $3;
   660  	}
   661  |	expr '<' '<' expr
   662  	{
   663  		$$ = $1 << $4;
   664  	}
   665  |	expr '>' '>' expr
   666  	{
   667  		$$ = $1 >> $4;
   668  	}
   669  |	expr '&' expr
   670  	{
   671  		$$ = $1 & $3;
   672  	}
   673  |	expr '^' expr
   674  	{
   675  		$$ = $1 ^ $3;
   676  	}
   677  |	expr '|' expr
   678  	{
   679  		$$ = $1 | $3;
   680  	}