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

     1  // cmd/9a/a.y from Vita Nuova.
     2  //
     3  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     4  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     5  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     6  //	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
     7  //	Portions Copyright © 2004,2006 Bruce Ellis
     8  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
     9  //	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
    10  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    11  //
    12  // Permission is hereby granted, free of charge, to any person obtaining a copy
    13  // of this software and associated documentation files (the "Software"), to deal
    14  // in the Software without restriction, including without limitation the rights
    15  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    16  // copies of the Software, and to permit persons to whom the Software is
    17  // furnished to do so, subject to the following conditions:
    18  //
    19  // The above copyright notice and this permission notice shall be included in
    20  // all copies or substantial portions of the Software.
    21  //
    22  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    23  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    24  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    25  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    26  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    27  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    28  // THE SOFTWARE.
    29  
    30  %{
    31  #include <u.h>
    32  #include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
    33  #include <libc.h>
    34  #include "a.h"
    35  #include "../../runtime/funcdata.h"
    36  %}
    37  %union
    38  {
    39  	Sym	*sym;
    40  	vlong	lval;
    41  	double	dval;
    42  	char	sval[8];
    43  	Addr	addr;
    44  }
    45  %left	'|'
    46  %left	'^'
    47  %left	'&'
    48  %left	'<' '>'
    49  %left	'+' '-'
    50  %left	'*' '/' '%'
    51  %token	<lval>	LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
    52  %token	<lval>	LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
    53  %token	<lval>	LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
    54  %token	<lval>	LCONST LSP LSB LFP LPC LCREG LFLUSH
    55  %token	<lval>	LREG LFREG LR LCR LF LFPSCR
    56  %token	<lval>	LLR LCTR LSPR LSPREG LSEG LMSR
    57  %token	<lval>	LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
    58  %token	<lval>	LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
    59  %token	<dval>	LFCONST
    60  %token	<sval>	LSCONST
    61  %token	<sym>	LNAME LLAB LVAR
    62  %type	<lval>	con expr pointer offset sreg
    63  %type	<addr>	addr rreg regaddr name creg freg xlreg lr ctr
    64  %type	<addr>	imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
    65  %%
    66  prog:
    67  |	prog line
    68  
    69  line:
    70  	LNAME ':'
    71  	{
    72  		$1 = labellookup($1);
    73  		if($1->type == LLAB && $1->value != pc)
    74  			yyerror("redeclaration of %s", $1->labelname);
    75  		$1->type = LLAB;
    76  		$1->value = pc;
    77  	}
    78  	line
    79  |	LNAME '=' expr ';'
    80  	{
    81  		$1->type = LVAR;
    82  		$1->value = $3;
    83  	}
    84  |	LVAR '=' expr ';'
    85  	{
    86  		if($1->value != $3)
    87  			yyerror("redeclaration of %s", $1->name);
    88  		$1->value = $3;
    89  	}
    90  |	LSCHED ';'
    91  	{
    92  		nosched = $1;
    93  	}
    94  |	';'
    95  |	inst ';'
    96  |	error ';'
    97  
    98  inst:
    99  /*
   100   * load ints and bytes
   101   */
   102  	LMOVW rreg ',' rreg
   103  	{
   104  		outcode($1, &$2, NREG, &$4);
   105  	}
   106  |	LMOVW addr ',' rreg
   107  	{
   108  		outcode($1, &$2, NREG, &$4);
   109  	}
   110  |	LMOVW regaddr ',' rreg
   111  	{
   112  		outcode($1, &$2, NREG, &$4);
   113  	}
   114  |	LMOVB rreg ',' rreg
   115  	{
   116  		outcode($1, &$2, NREG, &$4);
   117  	}
   118  |	LMOVB addr ',' rreg
   119  	{
   120  		outcode($1, &$2, NREG, &$4);
   121  	}
   122  |	LMOVB regaddr ',' rreg
   123  	{
   124  		outcode($1, &$2, NREG, &$4);
   125  	}
   126  /*
   127   * load floats
   128   */
   129  |	LFMOV addr ',' freg
   130  	{
   131  		outcode($1, &$2, NREG, &$4);
   132  	}
   133  |	LFMOV regaddr ',' freg
   134  	{
   135  		outcode($1, &$2, NREG, &$4);
   136  	}
   137  |	LFMOV fimm ',' freg
   138  	{
   139  		outcode($1, &$2, NREG, &$4);
   140  	}
   141  |	LFMOV freg ',' freg
   142  	{
   143  		outcode($1, &$2, NREG, &$4);
   144  	}
   145  |	LFMOV freg ',' addr
   146  	{
   147  		outcode($1, &$2, NREG, &$4);
   148  	}
   149  |	LFMOV freg ',' regaddr
   150  	{
   151  		outcode($1, &$2, NREG, &$4);
   152  	}
   153  /*
   154   * store ints and bytes
   155   */
   156  |	LMOVW rreg ',' addr
   157  	{
   158  		outcode($1, &$2, NREG, &$4);
   159  	}
   160  |	LMOVW rreg ',' regaddr
   161  	{
   162  		outcode($1, &$2, NREG, &$4);
   163  	}
   164  |	LMOVB rreg ',' addr
   165  	{
   166  		outcode($1, &$2, NREG, &$4);
   167  	}
   168  |	LMOVB rreg ',' regaddr
   169  	{
   170  		outcode($1, &$2, NREG, &$4);
   171  	}
   172  /*
   173   * store floats
   174   */
   175  |	LMOVW freg ',' addr
   176  	{
   177  		outcode($1, &$2, NREG, &$4);
   178  	}
   179  |	LMOVW freg ',' regaddr
   180  	{
   181  		outcode($1, &$2, NREG, &$4);
   182  	}
   183  /*
   184   * floating point status
   185   */
   186  |	LMOVW fpscr ',' freg
   187  	{
   188  		outcode($1, &$2, NREG, &$4);
   189  	}
   190  |	LMOVW freg ','  fpscr
   191  	{
   192  		outcode($1, &$2, NREG, &$4);
   193  	}
   194  |	LMOVW freg ',' imm ',' fpscr
   195  	{
   196  		outgcode($1, &$2, NREG, &$4, &$6);
   197  	}
   198  |	LMOVW fpscr ',' creg
   199  	{
   200  		outcode($1, &$2, NREG, &$4);
   201  	}
   202  |	LMOVW imm ',' fpscrf
   203  	{
   204  		outcode($1, &$2, NREG, &$4);
   205  	}
   206  |	LMTFSB imm ',' con
   207  	{
   208  		outcode($1, &$2, $4, &nullgen);
   209  	}
   210  /*
   211   * field moves (mtcrf)
   212   */
   213  |	LMOVW rreg ',' imm ',' lcr
   214  	{
   215  		outgcode($1, &$2, NREG, &$4, &$6);
   216  	}
   217  |	LMOVW rreg ',' creg
   218  	{
   219  		outcode($1, &$2, NREG, &$4);
   220  	}
   221  |	LMOVW rreg ',' lcr
   222  	{
   223  		outcode($1, &$2, NREG, &$4);
   224  	}
   225  /*
   226   * integer operations
   227   * logical instructions
   228   * shift instructions
   229   * unary instructions
   230   */
   231  |	LADDW rreg ',' sreg ',' rreg
   232  	{
   233  		outcode($1, &$2, $4, &$6);
   234  	}
   235  |	LADDW imm ',' sreg ',' rreg
   236  	{
   237  		outcode($1, &$2, $4, &$6);
   238  	}
   239  |	LADDW rreg ',' imm ',' rreg
   240  	{
   241  		outgcode($1, &$2, NREG, &$4, &$6);
   242  	}
   243  |	LADDW rreg ',' rreg
   244  	{
   245  		outcode($1, &$2, NREG, &$4);
   246  	}
   247  |	LADDW imm ',' rreg
   248  	{
   249  		outcode($1, &$2, NREG, &$4);
   250  	}
   251  |	LLOGW rreg ',' sreg ',' rreg
   252  	{
   253  		outcode($1, &$2, $4, &$6);
   254  	}
   255  |	LLOGW rreg ',' rreg
   256  	{
   257  		outcode($1, &$2, NREG, &$4);
   258  	}
   259  |	LSHW rreg ',' sreg ',' rreg
   260  	{
   261  		outcode($1, &$2, $4, &$6);
   262  	}
   263  |	LSHW rreg ',' rreg
   264  	{
   265  		outcode($1, &$2, NREG, &$4);
   266  	}
   267  |	LSHW imm ',' sreg ',' rreg
   268  	{
   269  		outcode($1, &$2, $4, &$6);
   270  	}
   271  |	LSHW imm ',' rreg
   272  	{
   273  		outcode($1, &$2, NREG, &$4);
   274  	}
   275  |	LABS rreg ',' rreg
   276  	{
   277  		outcode($1, &$2, NREG, &$4);
   278  	}
   279  |	LABS rreg
   280  	{
   281  		outcode($1, &$2, NREG, &$2);
   282  	}
   283  /*
   284   * multiply-accumulate
   285   */
   286  |	LMA rreg ',' sreg ',' rreg
   287  	{
   288  		outcode($1, &$2, $4, &$6);
   289  	}
   290  /*
   291   * move immediate: macro for cau+or, addi, addis, and other combinations
   292   */
   293  |	LMOVW imm ',' rreg
   294  	{
   295  		outcode($1, &$2, NREG, &$4);
   296  	}
   297  |	LMOVW ximm ',' rreg
   298  	{
   299  		outcode($1, &$2, NREG, &$4);
   300  	}
   301  /*
   302   * condition register operations
   303   */
   304  |	LCROP cbit ',' cbit
   305  	{
   306  		outcode($1, &$2, $4.reg, &$4);
   307  	}
   308  |	LCROP cbit ',' con ',' cbit
   309  	{
   310  		outcode($1, &$2, $4, &$6);
   311  	}
   312  /*
   313   * condition register moves
   314   * move from machine state register
   315   */
   316  |	LMOVW creg ',' creg
   317  	{
   318  		outcode($1, &$2, NREG, &$4);
   319  	}
   320  |	LMOVW psr ',' creg
   321  	{
   322  		outcode($1, &$2, NREG, &$4);
   323  	}
   324  |	LMOVW lcr ',' rreg
   325  	{
   326  		outcode($1, &$2, NREG, &$4);
   327  	}
   328  |	LMOVW psr ',' rreg
   329  	{
   330  		outcode($1, &$2, NREG, &$4);
   331  	}
   332  |	LMOVW xlreg ',' rreg
   333  	{
   334  		outcode($1, &$2, NREG, &$4);
   335  	}
   336  |	LMOVW rreg ',' xlreg
   337  	{
   338  		outcode($1, &$2, NREG, &$4);
   339  	}
   340  |	LMOVW creg ',' psr
   341  	{
   342  		outcode($1, &$2, NREG, &$4);
   343  	}
   344  |	LMOVW rreg ',' psr
   345  	{
   346  		outcode($1, &$2, NREG, &$4);
   347  	}
   348  /*
   349   * branch, branch conditional
   350   * branch conditional register
   351   * branch conditional to count register
   352   */
   353  |	LBRA rel
   354  	{
   355  		outcode($1, &nullgen, NREG, &$2);
   356  	}
   357  |	LBRA addr
   358  	{
   359  		outcode($1, &nullgen, NREG, &$2);
   360  	}
   361  |	LBRA '(' xlreg ')'
   362  	{
   363  		outcode($1, &nullgen, NREG, &$3);
   364  	}
   365  |	LBRA ',' rel
   366  	{
   367  		outcode($1, &nullgen, NREG, &$3);
   368  	}
   369  |	LBRA ',' addr
   370  	{
   371  		outcode($1, &nullgen, NREG, &$3);
   372  	}
   373  |	LBRA ',' '(' xlreg ')'
   374  	{
   375  		outcode($1, &nullgen, NREG, &$4);
   376  	}
   377  |	LBRA creg ',' rel
   378  	{
   379  		outcode($1, &$2, NREG, &$4);
   380  	}
   381  |	LBRA creg ',' addr
   382  	{
   383  		outcode($1, &$2, NREG, &$4);
   384  	}
   385  |	LBRA creg ',' '(' xlreg ')'
   386  	{
   387  		outcode($1, &$2, NREG, &$5);
   388  	}
   389  |	LBRA con ',' rel
   390  	{
   391  		outcode($1, &nullgen, $2, &$4);
   392  	}
   393  |	LBRA con ',' addr
   394  	{
   395  		outcode($1, &nullgen, $2, &$4);
   396  	}
   397  |	LBRA con ',' '(' xlreg ')'
   398  	{
   399  		outcode($1, &nullgen, $2, &$5);
   400  	}
   401  |	LBRA con ',' con ',' rel
   402  	{
   403  		Addr g;
   404  		g = nullgen;
   405  		g.type = D_CONST;
   406  		g.offset = $2;
   407  		outcode($1, &g, $4, &$6);
   408  	}
   409  |	LBRA con ',' con ',' addr
   410  	{
   411  		Addr g;
   412  		g = nullgen;
   413  		g.type = D_CONST;
   414  		g.offset = $2;
   415  		outcode($1, &g, $4, &$6);
   416  	}
   417  |	LBRA con ',' con ',' '(' xlreg ')'
   418  	{
   419  		Addr g;
   420  		g = nullgen;
   421  		g.type = D_CONST;
   422  		g.offset = $2;
   423  		outcode($1, &g, $4, &$7);
   424  	}
   425  /*
   426   * conditional trap
   427   */
   428  |	LTRAP rreg ',' sreg
   429  	{
   430  		outcode($1, &$2, $4, &nullgen);
   431  	}
   432  |	LTRAP imm ',' sreg
   433  	{
   434  		outcode($1, &$2, $4, &nullgen);
   435  	}
   436  |	LTRAP rreg comma
   437  	{
   438  		outcode($1, &$2, NREG, &nullgen);
   439  	}
   440  |	LTRAP comma
   441  	{
   442  		outcode($1, &nullgen, NREG, &nullgen);
   443  	}
   444  /*
   445   * floating point operate
   446   */
   447  |	LFCONV freg ',' freg
   448  	{
   449  		outcode($1, &$2, NREG, &$4);
   450  	}
   451  |	LFADD freg ',' freg
   452  	{
   453  		outcode($1, &$2, NREG, &$4);
   454  	}
   455  |	LFADD freg ',' freg ',' freg
   456  	{
   457  		outcode($1, &$2, $4.reg, &$6);
   458  	}
   459  |	LFMA freg ',' freg ',' freg ',' freg
   460  	{
   461  		outgcode($1, &$2, $4.reg, &$6, &$8);
   462  	}
   463  |	LFCMP freg ',' freg
   464  	{
   465  		outcode($1, &$2, NREG, &$4);
   466  	}
   467  |	LFCMP freg ',' freg ',' creg
   468  	{
   469  		outcode($1, &$2, $6.reg, &$4);
   470  	}
   471  /*
   472   * CMP
   473   */
   474  |	LCMP rreg ',' rreg
   475  	{
   476  		outcode($1, &$2, NREG, &$4);
   477  	}
   478  |	LCMP rreg ',' imm
   479  	{
   480  		outcode($1, &$2, NREG, &$4);
   481  	}
   482  |	LCMP rreg ',' rreg ',' creg
   483  	{
   484  		outcode($1, &$2, $6.reg, &$4);
   485  	}
   486  |	LCMP rreg ',' imm ',' creg
   487  	{
   488  		outcode($1, &$2, $6.reg, &$4);
   489  	}
   490  /*
   491   * rotate and mask
   492   */
   493  |	LRLWM  imm ',' rreg ',' imm ',' rreg
   494  	{
   495  		outgcode($1, &$2, $4.reg, &$6, &$8);
   496  	}
   497  |	LRLWM  imm ',' rreg ',' mask ',' rreg
   498  	{
   499  		outgcode($1, &$2, $4.reg, &$6, &$8);
   500  	}
   501  |	LRLWM  rreg ',' rreg ',' imm ',' rreg
   502  	{
   503  		outgcode($1, &$2, $4.reg, &$6, &$8);
   504  	}
   505  |	LRLWM  rreg ',' rreg ',' mask ',' rreg
   506  	{
   507  		outgcode($1, &$2, $4.reg, &$6, &$8);
   508  	}
   509  /*
   510   * load/store multiple
   511   */
   512  |	LMOVMW addr ',' rreg
   513  	{
   514  		outcode($1, &$2, NREG, &$4);
   515  	}
   516  |	LMOVMW rreg ',' addr
   517  	{
   518  		outcode($1, &$2, NREG, &$4);
   519  	}
   520  /*
   521   * various indexed load/store
   522   * indexed unary (eg, cache clear)
   523   */
   524  |	LXLD regaddr ',' rreg
   525  	{
   526  		outcode($1, &$2, NREG, &$4);
   527  	}
   528  |	LXLD regaddr ',' imm ',' rreg
   529  	{
   530  		outgcode($1, &$2, NREG, &$4, &$6);
   531  	}
   532  |	LXST rreg ',' regaddr
   533  	{
   534  		outcode($1, &$2, NREG, &$4);
   535  	}
   536  |	LXST rreg ',' imm ',' regaddr
   537  	{
   538  		outgcode($1, &$2, NREG, &$4, &$6);
   539  	}
   540  |	LXMV regaddr ',' rreg
   541  	{
   542  		outcode($1, &$2, NREG, &$4);
   543  	}
   544  |	LXMV rreg ',' regaddr
   545  	{
   546  		outcode($1, &$2, NREG, &$4);
   547  	}
   548  |	LXOP regaddr
   549  	{
   550  		outcode($1, &$2, NREG, &nullgen);
   551  	}
   552  /*
   553   * NOP
   554   */
   555  |	LNOP comma
   556  	{
   557  		outcode($1, &nullgen, NREG, &nullgen);
   558  	}
   559  |	LNOP rreg comma
   560  	{
   561  		outcode($1, &$2, NREG, &nullgen);
   562  	}
   563  |	LNOP freg comma
   564  	{
   565  		outcode($1, &$2, NREG, &nullgen);
   566  	}
   567  |	LNOP ',' rreg
   568  	{
   569  		outcode($1, &nullgen, NREG, &$3);
   570  	}
   571  |	LNOP ',' freg
   572  	{
   573  		outcode($1, &nullgen, NREG, &$3);
   574  	}
   575  |	LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
   576  	{
   577  		outcode($1, &$2, NREG, &nullgen);
   578  	}
   579  /*
   580   * word
   581   */
   582  |	LWORD imm comma
   583  	{
   584  		outcode($1, &$2, NREG, &nullgen);
   585  	}
   586  |	LWORD ximm comma
   587  	{
   588  		outcode($1, &$2, NREG, &nullgen);
   589  	}
   590  /*
   591   * PCDATA
   592   */
   593  |	LPCDAT imm ',' imm
   594  	{
   595  		if($2.type != D_CONST || $4.type != D_CONST)
   596  			yyerror("arguments to PCDATA must be integer constants");
   597  		outcode($1, &$2, NREG, &$4);
   598  	}
   599  /*
   600   * FUNCDATA
   601   */
   602  |	LFUNCDAT imm ',' addr
   603  	{
   604  		if($2.type != D_CONST)
   605  			yyerror("index for FUNCDATA must be integer constant");
   606  		if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
   607  			yyerror("value for FUNCDATA must be symbol reference");
   608   		outcode($1, &$2, NREG, &$4);
   609  	}
   610  /*
   611   * END
   612   */
   613  |	LEND comma
   614  	{
   615  		outcode($1, &nullgen, NREG, &nullgen);
   616  	}
   617  /*
   618   * TEXT/GLOBL
   619   */
   620  |	LTEXT name ',' imm
   621  	{
   622  		settext($2.sym);
   623  		outcode($1, &$2, NREG, &$4);
   624  	}
   625  |	LTEXT name ',' con ',' imm
   626  	{
   627  		settext($2.sym);
   628  		$6.offset &= 0xffffffffull;
   629  		$6.offset |= (vlong)ArgsSizeUnknown << 32;
   630  		outcode($1, &$2, $4, &$6);
   631  	}
   632  |	LTEXT name ',' con ',' imm '-' con
   633  	{
   634  		settext($2.sym);
   635  		$6.offset &= 0xffffffffull;
   636  		$6.offset |= ($8 & 0xffffffffull) << 32;
   637  		outcode($1, &$2, $4, &$6);
   638  	}
   639  /*
   640   * DATA
   641   */
   642  |	LDATA name '/' con ',' imm
   643  	{
   644  		outcode($1, &$2, $4, &$6);
   645  	}
   646  |	LDATA name '/' con ',' ximm
   647  	{
   648  		outcode($1, &$2, $4, &$6);
   649  	}
   650  |	LDATA name '/' con ',' fimm
   651  	{
   652  		outcode($1, &$2, $4, &$6);
   653  	}
   654  /*
   655   * RETURN
   656   */
   657  |	LRETRN	comma
   658  	{
   659  		outcode($1, &nullgen, NREG, &nullgen);
   660  	}
   661  
   662  rel:
   663  	con '(' LPC ')'
   664  	{
   665  		$$ = nullgen;
   666  		$$.type = D_BRANCH;
   667  		$$.offset = $1 + pc;
   668  	}
   669  |	LNAME offset
   670  	{
   671  		$1 = labellookup($1);
   672  		$$ = nullgen;
   673  		if(pass == 2 && $1->type != LLAB)
   674  			yyerror("undefined label: %s", $1->labelname);
   675  		$$.type = D_BRANCH;
   676  		$$.offset = $1->value + $2;
   677  	}
   678  
   679  rreg:
   680  	sreg
   681  	{
   682  		$$ = nullgen;
   683  		$$.type = D_REG;
   684  		$$.reg = $1;
   685  	}
   686  
   687  xlreg:
   688  	lr
   689  |	ctr
   690  
   691  lr:
   692  	LLR
   693  	{
   694  		$$ = nullgen;
   695  		$$.type = D_SPR;
   696  		$$.offset = $1;
   697  	}
   698  
   699  lcr:
   700  	LCR
   701  	{
   702  		$$ = nullgen;
   703  		$$.type = D_CREG;
   704  		$$.reg = NREG;	/* whole register */
   705  	}
   706  
   707  ctr:
   708  	LCTR
   709  	{
   710  		$$ = nullgen;
   711  		$$.type = D_SPR;
   712  		$$.offset = $1;
   713  	}
   714  
   715  msr:
   716  	LMSR
   717  	{
   718  		$$ = nullgen;
   719  		$$.type = D_MSR;
   720  	}
   721  
   722  psr:
   723  	LSPREG
   724  	{
   725  		$$ = nullgen;
   726  		$$.type = D_SPR;
   727  		$$.offset = $1;
   728  	}
   729  |	LSPR '(' con ')'
   730  	{
   731  		$$ = nullgen;
   732  		$$.type = $1;
   733  		$$.offset = $3;
   734  	}
   735  |	msr
   736  
   737  fpscr:
   738  	LFPSCR
   739  	{
   740  		$$ = nullgen;
   741  		$$.type = D_FPSCR;
   742  		$$.reg = NREG;
   743  	}
   744  
   745  fpscrf:
   746  	LFPSCR '(' con ')'
   747  	{
   748  		$$ = nullgen;
   749  		$$.type = D_FPSCR;
   750  		$$.reg = $3;
   751  	}
   752  
   753  freg:
   754  	LFREG
   755  	{
   756  		$$ = nullgen;
   757  		$$.type = D_FREG;
   758  		$$.reg = $1;
   759  	}
   760  |	LF '(' con ')'
   761  	{
   762  		$$ = nullgen;
   763  		$$.type = D_FREG;
   764  		$$.reg = $3;
   765  	}
   766  
   767  creg:
   768  	LCREG
   769  	{
   770  		$$ = nullgen;
   771  		$$.type = D_CREG;
   772  		$$.reg = $1;
   773  	}
   774  |	LCR '(' con ')'
   775  	{
   776  		$$ = nullgen;
   777  		$$.type = D_CREG;
   778  		$$.reg = $3;
   779  	}
   780  
   781  
   782  cbit:	con
   783  	{
   784  		$$ = nullgen;
   785  		$$.type = D_REG;
   786  		$$.reg = $1;
   787  	}
   788  
   789  mask:
   790  	con ',' con
   791  	{
   792  		int mb, me;
   793  		uint32 v;
   794  
   795  		$$ = nullgen;
   796  		$$.type = D_CONST;
   797  		mb = $1;
   798  		me = $3;
   799  		if(mb < 0 || mb > 31 || me < 0 || me > 31){
   800  			yyerror("illegal mask start/end value(s)");
   801  			mb = me = 0;
   802  		}
   803  		if(mb <= me)
   804  			v = ((uint32)~0L>>mb) & (~0L<<(31-me));
   805  		else
   806  			v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
   807  		$$.offset = v;
   808  	}
   809  
   810  ximm:
   811  	'$' addr
   812  	{
   813  		$$ = $2;
   814  		$$.type = D_CONST;
   815  	}
   816  |	'$' LSCONST
   817  	{
   818  		$$ = nullgen;
   819  		$$.type = D_SCONST;
   820  		memcpy($$.u.sval, $2, sizeof($$.u.sval));
   821  	}
   822  
   823  fimm:
   824  	'$' LFCONST
   825  	{
   826  		$$ = nullgen;
   827  		$$.type = D_FCONST;
   828  		$$.u.dval = $2;
   829  	}
   830  |	'$' '-' LFCONST
   831  	{
   832  		$$ = nullgen;
   833  		$$.type = D_FCONST;
   834  		$$.u.dval = -$3;
   835  	}
   836  
   837  imm:	'$' con
   838  	{
   839  		$$ = nullgen;
   840  		$$.type = D_CONST;
   841  		$$.offset = $2;
   842  	}
   843  
   844  sreg:
   845  	LREG
   846  |	LR '(' con ')'
   847  	{
   848  		if($$ < 0 || $$ >= NREG)
   849  			print("register value out of range\n");
   850  		$$ = $3;
   851  	}
   852  
   853  regaddr:
   854  	'(' sreg ')'
   855  	{
   856  		$$ = nullgen;
   857  		$$.type = D_OREG;
   858  		$$.reg = $2;
   859  		$$.offset = 0;
   860  	}
   861  |	'(' sreg '+' sreg ')'
   862  	{
   863  		$$ = nullgen;
   864  		$$.type = D_OREG;
   865  		$$.reg = $2;
   866  		$$.scale = $4;
   867  		$$.offset = 0;
   868  	}
   869  
   870  addr:
   871  	name
   872  |	con '(' sreg ')'
   873  	{
   874  		$$ = nullgen;
   875  		$$.type = D_OREG;
   876  		$$.reg = $3;
   877  		$$.offset = $1;
   878  	}
   879  
   880  name:
   881  	con '(' pointer ')'
   882  	{
   883  		$$ = nullgen;
   884  		$$.type = D_OREG;
   885  		$$.name = $3;
   886  		$$.sym = nil;
   887  		$$.offset = $1;
   888  	}
   889  |	LNAME offset '(' pointer ')'
   890  	{
   891  		$$ = nullgen;
   892  		$$.type = D_OREG;
   893  		$$.name = $4;
   894  		$$.sym = linklookup(ctxt, $1->name, 0);
   895  		$$.offset = $2;
   896  	}
   897  |	LNAME '<' '>' offset '(' LSB ')'
   898  	{
   899  		$$ = nullgen;
   900  		$$.type = D_OREG;
   901  		$$.name = D_STATIC;
   902  		$$.sym = linklookup(ctxt, $1->name, 0);
   903  		$$.offset = $4;
   904  	}
   905  
   906  comma:
   907  |	','
   908  
   909  offset:
   910  	{
   911  		$$ = 0;
   912  	}
   913  |	'+' con
   914  	{
   915  		$$ = $2;
   916  	}
   917  |	'-' con
   918  	{
   919  		$$ = -$2;
   920  	}
   921  
   922  pointer:
   923  	LSB
   924  |	LSP
   925  |	LFP
   926  
   927  con:
   928  	LCONST
   929  |	LVAR
   930  	{
   931  		$$ = $1->value;
   932  	}
   933  |	'-' con
   934  	{
   935  		$$ = -$2;
   936  	}
   937  |	'+' con
   938  	{
   939  		$$ = $2;
   940  	}
   941  |	'~' con
   942  	{
   943  		$$ = ~$2;
   944  	}
   945  |	'(' expr ')'
   946  	{
   947  		$$ = $2;
   948  	}
   949  
   950  expr:
   951  	con
   952  |	expr '+' expr
   953  	{
   954  		$$ = $1 + $3;
   955  	}
   956  |	expr '-' expr
   957  	{
   958  		$$ = $1 - $3;
   959  	}
   960  |	expr '*' expr
   961  	{
   962  		$$ = $1 * $3;
   963  	}
   964  |	expr '/' expr
   965  	{
   966  		$$ = $1 / $3;
   967  	}
   968  |	expr '%' expr
   969  	{
   970  		$$ = $1 % $3;
   971  	}
   972  |	expr '<' '<' expr
   973  	{
   974  		$$ = $1 << $4;
   975  	}
   976  |	expr '>' '>' expr
   977  	{
   978  		$$ = $1 >> $4;
   979  	}
   980  |	expr '&' expr
   981  	{
   982  		$$ = $1 & $3;
   983  	}
   984  |	expr '^' expr
   985  	{
   986  		$$ = $1 ^ $3;
   987  	}
   988  |	expr '|' expr
   989  	{
   990  		$$ = $1 | $3;
   991  	}