github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/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  #include "../../runtime/funcdata.h"
    37  %}
    38  %union
    39  {
    40  	Sym	*sym;
    41  	int32	lval;
    42  	double	dval;
    43  	char	sval[8];
    44  	Addr	addr;
    45  }
    46  %left	'|'
    47  %left	'^'
    48  %left	'&'
    49  %left	'<' '>'
    50  %left	'+' '-'
    51  %left	'*' '/' '%'
    52  %token	<lval>	LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
    53  %token	<lval>	LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
    54  %token	<lval>	LTYPEB LTYPEC LTYPED LTYPEE
    55  %token	<lval>	LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
    56  %token	<lval>	LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
    57  %token	<lval>	LCONST LSP LSB LFP LPC
    58  %token	<lval>	LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
    59  %token	<lval>	LCOND LS LAT
    60  %token	<dval>	LFCONST
    61  %token	<sval>	LSCONST
    62  %token	<sym>	LNAME LLAB LVAR
    63  %type	<lval>	con expr oexpr pointer offset sreg spreg creg
    64  %type	<lval>	rcon cond reglist
    65  %type	<addr>	gen rel reg regreg freg shift fcon frcon
    66  %type	<addr>	imm ximm name oreg ireg nireg ioreg imsr
    67  %%
    68  prog:
    69  |	prog
    70  	{
    71  		stmtline = lineno;
    72  	}
    73  	line
    74  
    75  line:
    76  	LNAME ':'
    77  	{
    78  		$1 = labellookup($1);
    79  		if($1->type == LLAB && $1->value != pc)
    80  			yyerror("redeclaration of %s", $1->labelname);
    81  		$1->type = LLAB;
    82  		$1->value = pc;
    83  	}
    84  	line
    85  |	LNAME '=' expr ';'
    86  	{
    87  		$1->type = LVAR;
    88  		$1->value = $3;
    89  	}
    90  |	LVAR '=' expr ';'
    91  	{
    92  		if($1->value != $3)
    93  			yyerror("redeclaration of %s", $1->name);
    94  		$1->value = $3;
    95  	}
    96  |	';'
    97  |	inst ';'
    98  |	error ';'
    99  
   100  inst:
   101  /*
   102   * ADD
   103   */
   104  	LTYPE1 cond imsr ',' spreg ',' reg
   105  	{
   106  		outcode($1, $2, &$3, $5, &$7);
   107  	}
   108  |	LTYPE1 cond imsr ',' spreg ','
   109  	{
   110  		outcode($1, $2, &$3, $5, &nullgen);
   111  	}
   112  |	LTYPE1 cond imsr ',' reg
   113  	{
   114  		outcode($1, $2, &$3, NREG, &$5);
   115  	}
   116  /*
   117   * MVN
   118   */
   119  |	LTYPE2 cond imsr ',' reg
   120  	{
   121  		outcode($1, $2, &$3, NREG, &$5);
   122  	}
   123  /*
   124   * MOVW
   125   */
   126  |	LTYPE3 cond gen ',' gen
   127  	{
   128  		outcode($1, $2, &$3, NREG, &$5);
   129  	}
   130  /*
   131   * B/BL
   132   */
   133  |	LTYPE4 cond comma rel
   134  	{
   135  		outcode($1, $2, &nullgen, NREG, &$4);
   136  	}
   137  |	LTYPE4 cond comma nireg
   138  	{
   139  		outcode($1, $2, &nullgen, NREG, &$4);
   140  	}
   141  /*
   142   * BX
   143   */
   144  |	LTYPEBX comma ireg
   145  	{
   146  		outcode($1, Always, &nullgen, NREG, &$3);
   147  	}
   148  /*
   149   * BEQ
   150   */
   151  |	LTYPE5 comma rel
   152  	{
   153  		outcode($1, Always, &nullgen, NREG, &$3);
   154  	}
   155  /*
   156   * SWI
   157   */
   158  |	LTYPE6 cond comma gen
   159  	{
   160  		outcode($1, $2, &nullgen, NREG, &$4);
   161  	}
   162  /*
   163   * CMP
   164   */
   165  |	LTYPE7 cond imsr ',' spreg comma
   166  	{
   167  		outcode($1, $2, &$3, $5, &nullgen);
   168  	}
   169  /*
   170   * MOVM
   171   */
   172  |	LTYPE8 cond ioreg ',' '[' reglist ']'
   173  	{
   174  		Addr g;
   175  
   176  		g = nullgen;
   177  		g.type = D_CONST;
   178  		g.offset = $6;
   179  		outcode($1, $2, &$3, NREG, &g);
   180  	}
   181  |	LTYPE8 cond '[' reglist ']' ',' ioreg
   182  	{
   183  		Addr g;
   184  
   185  		g = nullgen;
   186  		g.type = D_CONST;
   187  		g.offset = $4;
   188  		outcode($1, $2, &g, NREG, &$7);
   189  	}
   190  /*
   191   * SWAP
   192   */
   193  |	LTYPE9 cond reg ',' ireg ',' reg
   194  	{
   195  		outcode($1, $2, &$5, $3.reg, &$7);
   196  	}
   197  |	LTYPE9 cond reg ',' ireg comma
   198  	{
   199  		outcode($1, $2, &$5, $3.reg, &$3);
   200  	}
   201  |	LTYPE9 cond comma ireg ',' reg
   202  	{
   203  		outcode($1, $2, &$4, $6.reg, &$6);
   204  	}
   205  /*
   206   * RET
   207   */
   208  |	LTYPEA cond comma
   209  	{
   210  		outcode($1, $2, &nullgen, NREG, &nullgen);
   211  	}
   212  /*
   213   * TEXT/GLOBL
   214   */
   215  |	LTYPEB name ',' imm
   216  	{
   217  		settext($2.sym);
   218  		$4.type = D_CONST2;
   219  		$4.offset2 = ArgsSizeUnknown;
   220  		outcode($1, Always, &$2, 0, &$4);
   221  	}
   222  |	LTYPEB name ',' con ',' imm
   223  	{
   224  		settext($2.sym);
   225  		$6.type = D_CONST2;
   226  		$6.offset2 = ArgsSizeUnknown;
   227  		outcode($1, Always, &$2, $4, &$6);
   228  	}
   229  |	LTYPEB name ',' con ',' imm '-' con
   230  	{
   231  		settext($2.sym);
   232  		$6.type = D_CONST2;
   233  		$6.offset2 = $8;
   234  		outcode($1, Always, &$2, $4, &$6);
   235  	}
   236  /*
   237   * DATA
   238   */
   239  |	LTYPEC name '/' con ',' ximm
   240  	{
   241  		outcode($1, Always, &$2, $4, &$6);
   242  	}
   243  /*
   244   * CASE
   245   */
   246  |	LTYPED cond reg comma
   247  	{
   248  		outcode($1, $2, &$3, NREG, &nullgen);
   249  	}
   250  /*
   251   * word
   252   */
   253  |	LTYPEH comma ximm
   254  	{
   255  		outcode($1, Always, &nullgen, NREG, &$3);
   256  	}
   257  /*
   258   * floating-point coprocessor
   259   */
   260  |	LTYPEI cond freg ',' freg
   261  	{
   262  		outcode($1, $2, &$3, NREG, &$5);
   263  	}
   264  |	LTYPEK cond frcon ',' freg
   265  	{
   266  		outcode($1, $2, &$3, NREG, &$5);
   267  	}
   268  |	LTYPEK cond frcon ',' LFREG ',' freg
   269  	{
   270  		outcode($1, $2, &$3, $5, &$7);
   271  	}
   272  |	LTYPEL cond freg ',' freg comma
   273  	{
   274  		outcode($1, $2, &$3, $5.reg, &nullgen);
   275  	}
   276  /*
   277   * MCR MRC
   278   */
   279  |	LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
   280  	{
   281  		Addr g;
   282  
   283  		g = nullgen;
   284  		g.type = D_CONST;
   285  		g.offset =
   286  			(0xe << 24) |		/* opcode */
   287  			($1 << 20) |		/* MCR/MRC */
   288  			($2 << 28) |		/* scond */
   289  			(($3 & 15) << 8) |	/* coprocessor number */
   290  			(($5 & 7) << 21) |	/* coprocessor operation */
   291  			(($7 & 15) << 12) |	/* arm register */
   292  			(($9 & 15) << 16) |	/* Crn */
   293  			(($11 & 15) << 0) |	/* Crm */
   294  			(($12 & 7) << 5) |	/* coprocessor information */
   295  			(1<<4);			/* must be set */
   296  		outcode(AMRC, Always, &nullgen, NREG, &g);
   297  	}
   298  /*
   299   * MULL r1,r2,(hi,lo)
   300   */
   301  |	LTYPEM cond reg ',' reg ',' regreg
   302  	{
   303  		outcode($1, $2, &$3, $5.reg, &$7);
   304  	}
   305  /*
   306   * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
   307   * MULAW{T,B} r1,r2,r3,r4
   308   */
   309  |	LTYPEN cond reg ',' reg ',' reg ',' spreg
   310  	{
   311  		$7.type = D_REGREG2;
   312  		$7.offset = $9;
   313  		outcode($1, $2, &$3, $5.reg, &$7);
   314  	}
   315  /*
   316   * PLD
   317   */
   318  |	LTYPEPLD oreg
   319  	{
   320  		outcode($1, Always, &$2, NREG, &nullgen);
   321  	}
   322  /*
   323   * PCDATA
   324   */
   325  |	LTYPEPC gen ',' gen
   326  	{
   327  		if($2.type != D_CONST || $4.type != D_CONST)
   328  			yyerror("arguments to PCDATA must be integer constants");
   329  		outcode($1, Always, &$2, NREG, &$4);
   330  	}
   331  /*
   332   * FUNCDATA
   333   */
   334  |	LTYPEF gen ',' gen
   335  	{
   336  		if($2.type != D_CONST)
   337  			yyerror("index for FUNCDATA must be integer constant");
   338  		if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
   339  			yyerror("value for FUNCDATA must be symbol reference");
   340   		outcode($1, Always, &$2, NREG, &$4);
   341  	}
   342  /*
   343   * END
   344   */
   345  |	LTYPEE comma
   346  	{
   347  		outcode($1, Always, &nullgen, NREG, &nullgen);
   348  	}
   349  
   350  cond:
   351  	{
   352  		$$ = Always;
   353  	}
   354  |	cond LCOND
   355  	{
   356  		$$ = ($1 & ~C_SCOND) | $2;
   357  	}
   358  |	cond LS
   359  	{
   360  		$$ = $1 | $2;
   361  	}
   362  
   363  comma:
   364  |	',' comma
   365  
   366  rel:
   367  	con '(' LPC ')'
   368  	{
   369  		$$ = nullgen;
   370  		$$.type = D_BRANCH;
   371  		$$.offset = $1 + pc;
   372  	}
   373  |	LNAME offset
   374  	{
   375  		$1 = labellookup($1);
   376  		$$ = nullgen;
   377  		if(pass == 2 && $1->type != LLAB)
   378  			yyerror("undefined label: %s", $1->labelname);
   379  		$$.type = D_BRANCH;
   380  		$$.offset = $1->value + $2;
   381  	}
   382  
   383  ximm:	'$' con
   384  	{
   385  		$$ = nullgen;
   386  		$$.type = D_CONST;
   387  		$$.offset = $2;
   388  	}
   389  |	'$' oreg
   390  	{
   391  		$$ = $2;
   392  		$$.type = D_CONST;
   393  	}
   394  |	'$' '*' '$' oreg
   395  	{
   396  		$$ = $4;
   397  		$$.type = D_OCONST;
   398  	}
   399  |	'$' LSCONST
   400  	{
   401  		$$ = nullgen;
   402  		$$.type = D_SCONST;
   403  		memcpy($$.u.sval, $2, sizeof($$.u.sval));
   404  	}
   405  |	fcon
   406  
   407  fcon:
   408  	'$' LFCONST
   409  	{
   410  		$$ = nullgen;
   411  		$$.type = D_FCONST;
   412  		$$.u.dval = $2;
   413  	}
   414  |	'$' '-' LFCONST
   415  	{
   416  		$$ = nullgen;
   417  		$$.type = D_FCONST;
   418  		$$.u.dval = -$3;
   419  	}
   420  
   421  reglist:
   422  	spreg
   423  	{
   424  		$$ = 1 << $1;
   425  	}
   426  |	spreg '-' spreg
   427  	{
   428  		int i;
   429  		$$=0;
   430  		for(i=$1; i<=$3; i++)
   431  			$$ |= 1<<i;
   432  		for(i=$3; i<=$1; i++)
   433  			$$ |= 1<<i;
   434  	}
   435  |	spreg comma reglist
   436  	{
   437  		$$ = (1<<$1) | $3;
   438  	}
   439  
   440  gen:
   441  	reg
   442  |	ximm
   443  |	shift
   444  |	shift '(' spreg ')'
   445  	{
   446  		$$ = $1;
   447  		$$.reg = $3;
   448  	}
   449  |	LPSR
   450  	{
   451  		$$ = nullgen;
   452  		$$.type = D_PSR;
   453  		$$.reg = $1;
   454  	}
   455  |	LFCR
   456  	{
   457  		$$ = nullgen;
   458  		$$.type = D_FPCR;
   459  		$$.reg = $1;
   460  	}
   461  |	con
   462  	{
   463  		$$ = nullgen;
   464  		$$.type = D_OREG;
   465  		$$.offset = $1;
   466  	}
   467  |	oreg
   468  |	freg
   469  
   470  nireg:
   471  	ireg
   472  |	name
   473  	{
   474  		$$ = $1;
   475  		if($1.name != D_EXTERN && $1.name != D_STATIC) {
   476  		}
   477  	}
   478  
   479  ireg:
   480  	'(' spreg ')'
   481  	{
   482  		$$ = nullgen;
   483  		$$.type = D_OREG;
   484  		$$.reg = $2;
   485  		$$.offset = 0;
   486  	}
   487  
   488  ioreg:
   489  	ireg
   490  |	con '(' sreg ')'
   491  	{
   492  		$$ = nullgen;
   493  		$$.type = D_OREG;
   494  		$$.reg = $3;
   495  		$$.offset = $1;
   496  	}
   497  
   498  oreg:
   499  	name
   500  |	name '(' sreg ')'
   501  	{
   502  		$$ = $1;
   503  		$$.type = D_OREG;
   504  		$$.reg = $3;
   505  	}
   506  |	ioreg
   507  
   508  imsr:
   509  	reg
   510  |	imm
   511  |	shift
   512  
   513  imm:	'$' con
   514  	{
   515  		$$ = nullgen;
   516  		$$.type = D_CONST;
   517  		$$.offset = $2;
   518  	}
   519  
   520  reg:
   521  	spreg
   522  	{
   523  		$$ = nullgen;
   524  		$$.type = D_REG;
   525  		$$.reg = $1;
   526  	}
   527  
   528  regreg:
   529  	'(' spreg ',' spreg ')'
   530  	{
   531  		$$ = nullgen;
   532  		$$.type = D_REGREG;
   533  		$$.reg = $2;
   534  		$$.offset = $4;
   535  	}
   536  
   537  shift:
   538  	spreg '<' '<' rcon
   539  	{
   540  		$$ = nullgen;
   541  		$$.type = D_SHIFT;
   542  		$$.offset = $1 | $4 | (0 << 5);
   543  	}
   544  |	spreg '>' '>' rcon
   545  	{
   546  		$$ = nullgen;
   547  		$$.type = D_SHIFT;
   548  		$$.offset = $1 | $4 | (1 << 5);
   549  	}
   550  |	spreg '-' '>' rcon
   551  	{
   552  		$$ = nullgen;
   553  		$$.type = D_SHIFT;
   554  		$$.offset = $1 | $4 | (2 << 5);
   555  	}
   556  |	spreg LAT '>' rcon
   557  	{
   558  		$$ = nullgen;
   559  		$$.type = D_SHIFT;
   560  		$$.offset = $1 | $4 | (3 << 5);
   561  	}
   562  
   563  rcon:
   564  	spreg
   565  	{
   566  		if($$ < 0 || $$ >= 16)
   567  			print("register value out of range\n");
   568  		$$ = (($1&15) << 8) | (1 << 4);
   569  	}
   570  |	con
   571  	{
   572  		if($$ < 0 || $$ >= 32)
   573  			print("shift value out of range\n");
   574  		$$ = ($1&31) << 7;
   575  	}
   576  
   577  sreg:
   578  	LREG
   579  |	LPC
   580  	{
   581  		$$ = REGPC;
   582  	}
   583  |	LR '(' expr ')'
   584  	{
   585  		if($3 < 0 || $3 >= NREG)
   586  			print("register value out of range\n");
   587  		$$ = $3;
   588  	}
   589  
   590  spreg:
   591  	sreg
   592  |	LSP
   593  	{
   594  		$$ = REGSP;
   595  	}
   596  
   597  creg:
   598  	LCREG
   599  |	LC '(' expr ')'
   600  	{
   601  		if($3 < 0 || $3 >= NREG)
   602  			print("register value out of range\n");
   603  		$$ = $3;
   604  	}
   605  
   606  frcon:
   607  	freg
   608  |	fcon
   609  
   610  freg:
   611  	LFREG
   612  	{
   613  		$$ = nullgen;
   614  		$$.type = D_FREG;
   615  		$$.reg = $1;
   616  	}
   617  |	LF '(' con ')'
   618  	{
   619  		$$ = nullgen;
   620  		$$.type = D_FREG;
   621  		$$.reg = $3;
   622  	}
   623  
   624  name:
   625  	con '(' pointer ')'
   626  	{
   627  		$$ = nullgen;
   628  		$$.type = D_OREG;
   629  		$$.name = $3;
   630  		$$.sym = nil;
   631  		$$.offset = $1;
   632  	}
   633  |	LNAME offset '(' pointer ')'
   634  	{
   635  		$$ = nullgen;
   636  		$$.type = D_OREG;
   637  		$$.name = $4;
   638  		$$.sym = linklookup(ctxt, $1->name, 0);
   639  		$$.offset = $2;
   640  	}
   641  |	LNAME '<' '>' offset '(' LSB ')'
   642  	{
   643  		$$ = nullgen;
   644  		$$.type = D_OREG;
   645  		$$.name = D_STATIC;
   646  		$$.sym = linklookup(ctxt, $1->name, 1);
   647  		$$.offset = $4;
   648  	}
   649  
   650  offset:
   651  	{
   652  		$$ = 0;
   653  	}
   654  |	'+' con
   655  	{
   656  		$$ = $2;
   657  	}
   658  |	'-' con
   659  	{
   660  		$$ = -$2;
   661  	}
   662  
   663  pointer:
   664  	LSB
   665  |	LSP
   666  |	LFP
   667  
   668  con:
   669  	LCONST
   670  |	LVAR
   671  	{
   672  		$$ = $1->value;
   673  	}
   674  |	'-' con
   675  	{
   676  		$$ = -$2;
   677  	}
   678  |	'+' con
   679  	{
   680  		$$ = $2;
   681  	}
   682  |	'~' con
   683  	{
   684  		$$ = ~$2;
   685  	}
   686  |	'(' expr ')'
   687  	{
   688  		$$ = $2;
   689  	}
   690  
   691  oexpr:
   692  	{
   693  		$$ = 0;
   694  	}
   695  |	',' expr
   696  	{
   697  		$$ = $2;
   698  	}
   699  
   700  expr:
   701  	con
   702  |	expr '+' expr
   703  	{
   704  		$$ = $1 + $3;
   705  	}
   706  |	expr '-' expr
   707  	{
   708  		$$ = $1 - $3;
   709  	}
   710  |	expr '*' expr
   711  	{
   712  		$$ = $1 * $3;
   713  	}
   714  |	expr '/' expr
   715  	{
   716  		$$ = $1 / $3;
   717  	}
   718  |	expr '%' expr
   719  	{
   720  		$$ = $1 % $3;
   721  	}
   722  |	expr '<' '<' expr
   723  	{
   724  		$$ = $1 << $4;
   725  	}
   726  |	expr '>' '>' expr
   727  	{
   728  		$$ = $1 >> $4;
   729  	}
   730  |	expr '&' expr
   731  	{
   732  		$$ = $1 & $3;
   733  	}
   734  |	expr '^' expr
   735  	{
   736  		$$ = $1 ^ $3;
   737  	}
   738  |	expr '|' expr
   739  	{
   740  		$$ = $1 | $3;
   741  	}