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