github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/old9a/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  package main
    32  
    33  import (
    34  	"cmd/internal/asm"
    35  	"cmd/internal/obj"
    36  	. "cmd/internal/obj/ppc64"
    37  )
    38  %}
    39  
    40  %union
    41  {
    42  	sym *asm.Sym
    43  	lval int64
    44  	dval float64
    45  	sval string
    46  	addr obj.Addr
    47  }
    48  
    49  %left	'|'
    50  %left	'^'
    51  %left	'&'
    52  %left	'<' '>'
    53  %left	'+' '-'
    54  %left	'*' '/' '%'
    55  %token	<lval>	LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
    56  %token	<lval>	LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
    57  %token	<lval>	LNOP LEND LRETT LWORD LTEXT LDATA LGLOBL LRETRN
    58  %token	<lval>	LCONST LSP LSB LFP LPC LCREG LFLUSH
    59  %token	<lval>	LREG LFREG LR LCR LF LFPSCR
    60  %token	<lval>	LLR LCTR LSPR LSPREG LSEG LMSR
    61  %token	<lval>	LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
    62  %token	<lval>	LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
    63  %token	<dval>	LFCONST
    64  %token	<sval>	LSCONST
    65  %token	<sym>	LNAME LLAB LVAR
    66  %type	<lval>	con expr pointer offset sreg
    67  %type	<addr>	addr rreg regaddr name creg freg xlreg lr ctr textsize
    68  %type	<addr>	imm ximm fimm rel psr lcr cbit fpscr msr mask
    69  %%
    70  prog:
    71  |	prog
    72  	{
    73  		stmtline = asm.Lineno
    74  	}
    75  	line
    76  
    77  line:
    78  	LNAME ':'
    79  	{
    80  		$1 = asm.LabelLookup($1);
    81  		if $1.Type == LLAB && $1.Value != int64(asm.PC) {
    82  			yyerror("redeclaration of %s", $1.Labelname)
    83  		}
    84  		$1.Type = LLAB;
    85  		$1.Value = int64(asm.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  		}
    98  		$1.Value = $3;
    99  	}
   100  |	LSCHED ';'
   101  	{
   102  		nosched = int($1);
   103  	}
   104  |	';'
   105  |	inst ';'
   106  |	error ';'
   107  
   108  inst:
   109  /*
   110   * load ints and bytes
   111   */
   112  	LMOVW rreg ',' rreg
   113  	{
   114  		outcode(int($1), &$2, 0, &$4);
   115  	}
   116  |	LMOVW addr ',' rreg
   117  	{
   118  		outcode(int($1), &$2, 0, &$4);
   119  	}
   120  |	LMOVW regaddr ',' rreg
   121  	{
   122  		outcode(int($1), &$2, 0, &$4);
   123  	}
   124  |	LMOVB rreg ',' rreg
   125  	{
   126  		outcode(int($1), &$2, 0, &$4);
   127  	}
   128  |	LMOVB addr ',' rreg
   129  	{
   130  		outcode(int($1), &$2, 0, &$4);
   131  	}
   132  |	LMOVB regaddr ',' rreg
   133  	{
   134  		outcode(int($1), &$2, 0, &$4);
   135  	}
   136  /*
   137   * load floats
   138   */
   139  |	LFMOV addr ',' freg
   140  	{
   141  		outcode(int($1), &$2, 0, &$4);
   142  	}
   143  |	LFMOV regaddr ',' freg
   144  	{
   145  		outcode(int($1), &$2, 0, &$4);
   146  	}
   147  |	LFMOV fimm ',' freg
   148  	{
   149  		outcode(int($1), &$2, 0, &$4);
   150  	}
   151  |	LFMOV freg ',' freg
   152  	{
   153  		outcode(int($1), &$2, 0, &$4);
   154  	}
   155  |	LFMOV freg ',' addr
   156  	{
   157  		outcode(int($1), &$2, 0, &$4);
   158  	}
   159  |	LFMOV freg ',' regaddr
   160  	{
   161  		outcode(int($1), &$2, 0, &$4);
   162  	}
   163  /*
   164   * store ints and bytes
   165   */
   166  |	LMOVW rreg ',' addr
   167  	{
   168  		outcode(int($1), &$2, 0, &$4);
   169  	}
   170  |	LMOVW rreg ',' regaddr
   171  	{
   172  		outcode(int($1), &$2, 0, &$4);
   173  	}
   174  |	LMOVB rreg ',' addr
   175  	{
   176  		outcode(int($1), &$2, 0, &$4);
   177  	}
   178  |	LMOVB rreg ',' regaddr
   179  	{
   180  		outcode(int($1), &$2, 0, &$4);
   181  	}
   182  /*
   183   * store floats
   184   */
   185  |	LMOVW freg ',' addr
   186  	{
   187  		outcode(int($1), &$2, 0, &$4);
   188  	}
   189  |	LMOVW freg ',' regaddr
   190  	{
   191  		outcode(int($1), &$2, 0, &$4);
   192  	}
   193  /*
   194   * floating point status
   195   */
   196  |	LMOVW fpscr ',' freg
   197  	{
   198  		outcode(int($1), &$2, 0, &$4);
   199  	}
   200  |	LMOVW freg ','  fpscr
   201  	{
   202  		outcode(int($1), &$2, 0, &$4);
   203  	}
   204  |	LMOVW freg ',' imm ',' fpscr
   205  	{
   206  		outgcode(int($1), &$2, 0, &$4, &$6);
   207  	}
   208  |	LMOVW fpscr ',' creg
   209  	{
   210  		outcode(int($1), &$2, 0, &$4);
   211  	}
   212  |	LMTFSB imm ',' con
   213  	{
   214  		outcode(int($1), &$2, int($4), &nullgen);
   215  	}
   216  /*
   217   * field moves (mtcrf)
   218   */
   219  |	LMOVW rreg ',' imm ',' lcr
   220  	{
   221  		outgcode(int($1), &$2, 0, &$4, &$6);
   222  	}
   223  |	LMOVW rreg ',' creg
   224  	{
   225  		outcode(int($1), &$2, 0, &$4);
   226  	}
   227  |	LMOVW rreg ',' lcr
   228  	{
   229  		outcode(int($1), &$2, 0, &$4);
   230  	}
   231  /*
   232   * integer operations
   233   * logical instructions
   234   * shift instructions
   235   * unary instructions
   236   */
   237  |	LADDW rreg ',' sreg ',' rreg
   238  	{
   239  		outcode(int($1), &$2, int($4), &$6);
   240  	}
   241  |	LADDW imm ',' sreg ',' rreg
   242  	{
   243  		outcode(int($1), &$2, int($4), &$6);
   244  	}
   245  |	LADDW rreg ',' imm ',' rreg
   246  	{
   247  		outgcode(int($1), &$2, 0, &$4, &$6);
   248  	}
   249  |	LADDW rreg ',' rreg
   250  	{
   251  		outcode(int($1), &$2, 0, &$4);
   252  	}
   253  |	LADDW imm ',' rreg
   254  	{
   255  		outcode(int($1), &$2, 0, &$4);
   256  	}
   257  |	LLOGW rreg ',' sreg ',' rreg
   258  	{
   259  		outcode(int($1), &$2, int($4), &$6);
   260  	}
   261  |	LLOGW rreg ',' rreg
   262  	{
   263  		outcode(int($1), &$2, 0, &$4);
   264  	}
   265  |	LSHW rreg ',' sreg ',' rreg
   266  	{
   267  		outcode(int($1), &$2, int($4), &$6);
   268  	}
   269  |	LSHW rreg ',' rreg
   270  	{
   271  		outcode(int($1), &$2, 0, &$4);
   272  	}
   273  |	LSHW imm ',' sreg ',' rreg
   274  	{
   275  		outcode(int($1), &$2, int($4), &$6);
   276  	}
   277  |	LSHW imm ',' rreg
   278  	{
   279  		outcode(int($1), &$2, 0, &$4);
   280  	}
   281  |	LABS rreg ',' rreg
   282  	{
   283  		outcode(int($1), &$2, 0, &$4);
   284  	}
   285  |	LABS rreg
   286  	{
   287  		outcode(int($1), &$2, 0, &$2);
   288  	}
   289  /*
   290   * multiply-accumulate
   291   */
   292  |	LMA rreg ',' sreg ',' rreg
   293  	{
   294  		outcode(int($1), &$2, int($4), &$6);
   295  	}
   296  /*
   297   * move immediate: macro for cau+or, addi, addis, and other combinations
   298   */
   299  |	LMOVW imm ',' rreg
   300  	{
   301  		outcode(int($1), &$2, 0, &$4);
   302  	}
   303  |	LMOVW ximm ',' rreg
   304  	{
   305  		outcode(int($1), &$2, 0, &$4);
   306  	}
   307  /*
   308   * condition register operations
   309   */
   310  |	LCROP cbit ',' cbit
   311  	{
   312  		outcode(int($1), &$2, int($4.Reg), &$4);
   313  	}
   314  |	LCROP cbit ',' con ',' cbit
   315  	{
   316  		outcode(int($1), &$2, int($4), &$6);
   317  	}
   318  /*
   319   * condition register moves
   320   * move from machine state register
   321   */
   322  |	LMOVW creg ',' creg
   323  	{
   324  		outcode(int($1), &$2, 0, &$4);
   325  	}
   326  |	LMOVW psr ',' creg
   327  	{
   328  		outcode(int($1), &$2, 0, &$4);
   329  	}
   330  |	LMOVW lcr ',' rreg
   331  	{
   332  		outcode(int($1), &$2, 0, &$4);
   333  	}
   334  |	LMOVW psr ',' rreg
   335  	{
   336  		outcode(int($1), &$2, 0, &$4);
   337  	}
   338  |	LMOVW xlreg ',' rreg
   339  	{
   340  		outcode(int($1), &$2, 0, &$4);
   341  	}
   342  |	LMOVW rreg ',' xlreg
   343  	{
   344  		outcode(int($1), &$2, 0, &$4);
   345  	}
   346  |	LMOVW creg ',' psr
   347  	{
   348  		outcode(int($1), &$2, 0, &$4);
   349  	}
   350  |	LMOVW rreg ',' psr
   351  	{
   352  		outcode(int($1), &$2, 0, &$4);
   353  	}
   354  /*
   355   * branch, branch conditional
   356   * branch conditional register
   357   * branch conditional to count register
   358   */
   359  |	LBRA rel
   360  	{
   361  		outcode(int($1), &nullgen, 0, &$2);
   362  	}
   363  |	LBRA addr
   364  	{
   365  		outcode(int($1), &nullgen, 0, &$2);
   366  	}
   367  |	LBRA '(' xlreg ')'
   368  	{
   369  		outcode(int($1), &nullgen, 0, &$3);
   370  	}
   371  |	LBRA ',' rel
   372  	{
   373  		outcode(int($1), &nullgen, 0, &$3);
   374  	}
   375  |	LBRA ',' addr
   376  	{
   377  		outcode(int($1), &nullgen, 0, &$3);
   378  	}
   379  |	LBRA ',' '(' xlreg ')'
   380  	{
   381  		outcode(int($1), &nullgen, 0, &$4);
   382  	}
   383  |	LBRA creg ',' rel
   384  	{
   385  		outcode(int($1), &$2, 0, &$4);
   386  	}
   387  |	LBRA creg ',' addr
   388  	{
   389  		outcode(int($1), &$2, 0, &$4);
   390  	}
   391  |	LBRA creg ',' '(' xlreg ')'
   392  	{
   393  		outcode(int($1), &$2, 0, &$5);
   394  	}
   395  |	LBRA con ',' rel
   396  	{
   397  		outcode(int($1), &nullgen, int($2), &$4);
   398  	}
   399  |	LBRA con ',' addr
   400  	{
   401  		outcode(int($1), &nullgen, int($2), &$4);
   402  	}
   403  |	LBRA con ',' '(' xlreg ')'
   404  	{
   405  		outcode(int($1), &nullgen, int($2), &$5);
   406  	}
   407  |	LBRA con ',' con ',' rel
   408  	{
   409  		var g obj.Addr
   410  		g = nullgen;
   411  		g.Type = obj.TYPE_CONST;
   412  		g.Offset = $2;
   413  		outcode(int($1), &g, int(REG_R0+$4), &$6);
   414  	}
   415  |	LBRA con ',' con ',' addr
   416  	{
   417  		var g obj.Addr
   418  		g = nullgen;
   419  		g.Type = obj.TYPE_CONST;
   420  		g.Offset = $2;
   421  		outcode(int($1), &g, int(REG_R0+$4), &$6);
   422  	}
   423  |	LBRA con ',' con ',' '(' xlreg ')'
   424  	{
   425  		var g obj.Addr
   426  		g = nullgen;
   427  		g.Type = obj.TYPE_CONST;
   428  		g.Offset = $2;
   429  		outcode(int($1), &g, int(REG_R0+$4), &$7);
   430  	}
   431  /*
   432   * conditional trap
   433   */
   434  |	LTRAP rreg ',' sreg
   435  	{
   436  		outcode(int($1), &$2, int($4), &nullgen);
   437  	}
   438  |	LTRAP imm ',' sreg
   439  	{
   440  		outcode(int($1), &$2, int($4), &nullgen);
   441  	}
   442  |	LTRAP rreg comma
   443  	{
   444  		outcode(int($1), &$2, 0, &nullgen);
   445  	}
   446  |	LTRAP comma
   447  	{
   448  		outcode(int($1), &nullgen, 0, &nullgen);
   449  	}
   450  /*
   451   * floating point operate
   452   */
   453  |	LFCONV freg ',' freg
   454  	{
   455  		outcode(int($1), &$2, 0, &$4);
   456  	}
   457  |	LFADD freg ',' freg
   458  	{
   459  		outcode(int($1), &$2, 0, &$4);
   460  	}
   461  |	LFADD freg ',' freg ',' freg
   462  	{
   463  		outcode(int($1), &$2, int($4.Reg), &$6);
   464  	}
   465  |	LFMA freg ',' freg ',' freg ',' freg
   466  	{
   467  		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
   468  	}
   469  |	LFCMP freg ',' freg
   470  	{
   471  		outcode(int($1), &$2, 0, &$4);
   472  	}
   473  |	LFCMP freg ',' freg ',' creg
   474  	{
   475  		outcode(int($1), &$2, int($6.Reg), &$4);
   476  	}
   477  /*
   478   * CMP
   479   */
   480  |	LCMP rreg ',' rreg
   481  	{
   482  		outcode(int($1), &$2, 0, &$4);
   483  	}
   484  |	LCMP rreg ',' imm
   485  	{
   486  		outcode(int($1), &$2, 0, &$4);
   487  	}
   488  |	LCMP rreg ',' rreg ',' creg
   489  	{
   490  		outcode(int($1), &$2, int($6.Reg), &$4);
   491  	}
   492  |	LCMP rreg ',' imm ',' creg
   493  	{
   494  		outcode(int($1), &$2, int($6.Reg), &$4);
   495  	}
   496  /*
   497   * rotate and mask
   498   */
   499  |	LRLWM  imm ',' rreg ',' imm ',' rreg
   500  	{
   501  		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
   502  	}
   503  |	LRLWM  imm ',' rreg ',' mask ',' rreg
   504  	{
   505  		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
   506  	}
   507  |	LRLWM  rreg ',' rreg ',' imm ',' rreg
   508  	{
   509  		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
   510  	}
   511  |	LRLWM  rreg ',' rreg ',' mask ',' rreg
   512  	{
   513  		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
   514  	}
   515  /*
   516   * load/store multiple
   517   */
   518  |	LMOVMW addr ',' rreg
   519  	{
   520  		outcode(int($1), &$2, 0, &$4);
   521  	}
   522  |	LMOVMW rreg ',' addr
   523  	{
   524  		outcode(int($1), &$2, 0, &$4);
   525  	}
   526  /*
   527   * various indexed load/store
   528   * indexed unary (eg, cache clear)
   529   */
   530  |	LXLD regaddr ',' rreg
   531  	{
   532  		outcode(int($1), &$2, 0, &$4);
   533  	}
   534  |	LXLD regaddr ',' imm ',' rreg
   535  	{
   536  		outgcode(int($1), &$2, 0, &$4, &$6);
   537  	}
   538  |	LXST rreg ',' regaddr
   539  	{
   540  		outcode(int($1), &$2, 0, &$4);
   541  	}
   542  |	LXST rreg ',' imm ',' regaddr
   543  	{
   544  		outgcode(int($1), &$2, 0, &$4, &$6);
   545  	}
   546  |	LXMV regaddr ',' rreg
   547  	{
   548  		outcode(int($1), &$2, 0, &$4);
   549  	}
   550  |	LXMV rreg ',' regaddr
   551  	{
   552  		outcode(int($1), &$2, 0, &$4);
   553  	}
   554  |	LXOP regaddr
   555  	{
   556  		outcode(int($1), &$2, 0, &nullgen);
   557  	}
   558  /*
   559   * NOP
   560   */
   561  |	LNOP comma
   562  	{
   563  		outcode(int($1), &nullgen, 0, &nullgen);
   564  	}
   565  |	LNOP rreg comma
   566  	{
   567  		outcode(int($1), &$2, 0, &nullgen);
   568  	}
   569  |	LNOP freg comma
   570  	{
   571  		outcode(int($1), &$2, 0, &nullgen);
   572  	}
   573  |	LNOP ',' rreg
   574  	{
   575  		outcode(int($1), &nullgen, 0, &$3);
   576  	}
   577  |	LNOP ',' freg
   578  	{
   579  		outcode(int($1), &nullgen, 0, &$3);
   580  	}
   581  |	LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
   582  	{
   583  		outcode(int($1), &$2, 0, &nullgen);
   584  	}
   585  /*
   586   * word
   587   */
   588  |	LWORD imm comma
   589  	{
   590  		outcode(int($1), &$2, 0, &nullgen);
   591  	}
   592  |	LWORD ximm comma
   593  	{
   594  		outcode(int($1), &$2, 0, &nullgen);
   595  	}
   596  /*
   597   * PCDATA
   598   */
   599  |	LPCDAT imm ',' imm
   600  	{
   601  		if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
   602  			yyerror("arguments to PCDATA must be integer constants")
   603  		}
   604  		outcode(int($1), &$2, 0, &$4);
   605  	}
   606  /*
   607   * FUNCDATA
   608   */
   609  |	LFUNCDAT imm ',' addr
   610  	{
   611  		if $2.Type != obj.TYPE_CONST {
   612  			yyerror("index for FUNCDATA must be integer constant")
   613  		}
   614  		if $4.Type != obj.TYPE_MEM || ($4.Name != obj.NAME_EXTERN && $4.Name != obj.NAME_STATIC) {
   615  			yyerror("value for FUNCDATA must be symbol reference")
   616  		}
   617   		outcode(int($1), &$2, 0, &$4);
   618  	}
   619  /*
   620   * END
   621   */
   622  |	LEND comma
   623  	{
   624  		outcode(int($1), &nullgen, 0, &nullgen);
   625  	}
   626  /*
   627   * TEXT
   628   */
   629  |	LTEXT name ',' '$' textsize
   630  	{
   631  		asm.Settext($2.Sym);
   632  		outcode(int($1), &$2, 0, &$5);
   633  	}
   634  |	LTEXT name ',' con ',' '$' textsize
   635  	{
   636  		asm.Settext($2.Sym);
   637  		outcode(int($1), &$2, int($4), &$7);
   638  		if asm.Pass > 1 {
   639  			lastpc.From3.Type = obj.TYPE_CONST
   640  			lastpc.From3.Offset = $4
   641  		}
   642  	}
   643  /*
   644   * GLOBL
   645   */
   646  |	LGLOBL name ',' imm
   647  	{
   648  		asm.Settext($2.Sym)
   649  		outcode(int($1), &$2, 0, &$4)
   650  	}
   651  |	LGLOBL name ',' con ',' imm
   652  	{
   653  		asm.Settext($2.Sym)
   654  		outcode(int($1), &$2, 0, &$6)
   655  		if asm.Pass > 1 {
   656  			lastpc.From3.Type = obj.TYPE_CONST
   657  			lastpc.From3.Offset = $4
   658  		}
   659  	}
   660  
   661  /*
   662   * DATA
   663   */
   664  |	LDATA name '/' con ',' imm
   665  	{
   666  		outcode(int($1), &$2, 0, &$6);
   667  		if asm.Pass > 1 {
   668  			lastpc.From3.Type = obj.TYPE_CONST
   669  			lastpc.From3.Offset = $4
   670  		}
   671  	}
   672  |	LDATA name '/' con ',' ximm
   673  	{
   674  		outcode(int($1), &$2, 0, &$6);
   675  		if asm.Pass > 1 {
   676  			lastpc.From3.Type = obj.TYPE_CONST
   677  			lastpc.From3.Offset = $4
   678  		}
   679  	}
   680  |	LDATA name '/' con ',' fimm
   681  	{
   682  		outcode(int($1), &$2, 0, &$6);
   683  		if asm.Pass > 1 {
   684  			lastpc.From3.Type = obj.TYPE_CONST
   685  			lastpc.From3.Offset = $4
   686  		}
   687  	}
   688  /*
   689   * RETURN
   690   */
   691  |	LRETRN	comma
   692  	{
   693  		outcode(int($1), &nullgen, 0, &nullgen);
   694  	}
   695  
   696  rel:
   697  	con '(' LPC ')'
   698  	{
   699  		$$ = nullgen;
   700  		$$.Type = obj.TYPE_BRANCH;
   701  		$$.Offset = $1 + int64(asm.PC);
   702  	}
   703  |	LNAME offset
   704  	{
   705  		$1 = asm.LabelLookup($1);
   706  		$$ = nullgen;
   707  		if asm.Pass == 2 && $1.Type != LLAB {
   708  			yyerror("undefined label: %s", $1.Labelname)
   709  		}
   710  		$$.Type = obj.TYPE_BRANCH;
   711  		$$.Offset = $1.Value + $2;
   712  	}
   713  
   714  rreg:
   715  	sreg
   716  	{
   717  		$$ = nullgen;
   718  		$$.Type = obj.TYPE_REG;
   719  		$$.Reg = int16($1);
   720  	}
   721  
   722  xlreg:
   723  	lr
   724  |	ctr
   725  
   726  lr:
   727  	LLR
   728  	{
   729  		$$ = nullgen;
   730  		$$.Type = obj.TYPE_REG;
   731  		$$.Reg = int16($1);
   732  	}
   733  
   734  lcr:
   735  	LCR
   736  	{
   737  		$$ = nullgen;
   738  		$$.Type = obj.TYPE_REG;
   739  		$$.Reg = int16($1);	/* whole register */
   740  	}
   741  
   742  ctr:
   743  	LCTR
   744  	{
   745  		$$ = nullgen;
   746  		$$.Type = obj.TYPE_REG;
   747  		$$.Reg = int16($1);
   748  	}
   749  
   750  msr:
   751  	LMSR
   752  	{
   753  		$$ = nullgen;
   754  		$$.Type = obj.TYPE_REG;
   755  		$$.Reg = int16($1)
   756  	}
   757  
   758  psr:
   759  	LSPREG
   760  	{
   761  		$$ = nullgen;
   762  		$$.Type = obj.TYPE_REG;
   763  		$$.Reg = int16($1);
   764  	}
   765  |	LSPR '(' con ')'
   766  	{
   767  		if $3 < 0 || $3 >= 1024 {
   768  			yyerror("SPR/DCR out of range")
   769  		}
   770  		$$ = nullgen;
   771  		$$.Type = obj.TYPE_REG
   772  		$$.Reg = int16($1 + $3);
   773  	}
   774  |	msr
   775  
   776  fpscr:
   777  	LFPSCR
   778  	{
   779  		$$ = nullgen;
   780  		$$.Type = obj.TYPE_REG;
   781  		$$.Reg = int16($1);
   782  	}
   783  
   784  freg:
   785  	LFREG
   786  	{
   787  		$$ = nullgen;
   788  		$$.Type = obj.TYPE_REG;
   789  		$$.Reg = int16($1);
   790  	}
   791  |	LF '(' con ')'
   792  	{
   793  		$$ = nullgen;
   794  		$$.Type = obj.TYPE_REG;
   795  		$$.Reg = int16(REG_F0 + $3);
   796  	}
   797  
   798  creg:
   799  	LCREG
   800  	{
   801  		$$ = nullgen;
   802  		$$.Type = obj.TYPE_REG;
   803  		$$.Reg = int16($1);
   804  	}
   805  |	LCR '(' con ')'
   806  	{
   807  		$$ = nullgen;
   808  		$$.Type = obj.TYPE_REG;
   809  		$$.Reg = int16(REG_CR0 + $3);
   810  	}
   811  
   812  
   813  cbit:	con
   814  	{
   815  		$$ = nullgen;
   816  		$$.Type = obj.TYPE_REG;
   817  		$$.Reg = int16($1);
   818  	}
   819  
   820  mask:
   821  	con ',' con
   822  	{
   823  		var mb, me int
   824  		var v uint32
   825  
   826  		$$ = nullgen;
   827  		$$.Type = obj.TYPE_CONST;
   828  		mb = int($1);
   829  		me = int($3);
   830  		if(mb < 0 || mb > 31 || me < 0 || me > 31){
   831  			yyerror("illegal mask start/end value(s)");
   832  			mb = 0
   833  			me = 0;
   834  		}
   835  		if mb <= me {
   836  			v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
   837  		} else {
   838  			v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
   839  		}
   840  		$$.Offset = int64(v);
   841  	}
   842  
   843  textsize:
   844  	LCONST
   845  	{
   846  		$$ = nullgen;
   847  		$$.Type = obj.TYPE_TEXTSIZE;
   848  		$$.Offset = int64($1)
   849  		$$.Val = int32(obj.ArgsSizeUnknown);
   850  	}
   851  |	'-' LCONST
   852  	{
   853  		$$ = nullgen;
   854  		$$.Type = obj.TYPE_TEXTSIZE;
   855  		$$.Offset = -int64($2)
   856  		$$.Val = int32(obj.ArgsSizeUnknown);
   857  	}
   858  |	LCONST '-' LCONST
   859  	{
   860  		$$ = nullgen;
   861  		$$.Type = obj.TYPE_TEXTSIZE;
   862  		$$.Offset = int64($1)
   863  		$$.Val = int32($3);
   864  	}
   865  |	'-' LCONST '-' LCONST
   866  	{
   867  		$$ = nullgen;
   868  		$$.Type = obj.TYPE_TEXTSIZE;
   869  		$$.Offset = -int64($2)
   870  		$$.Val = int32($4);
   871  	}
   872  
   873  ximm:
   874  	'$' addr
   875  	{
   876  		$$ = $2;
   877  		$$.Type = obj.TYPE_ADDR;
   878  	}
   879  |	'$' LSCONST
   880  	{
   881  		$$ = nullgen;
   882  		$$.Type = obj.TYPE_SCONST;
   883  		$$.Val = $2
   884  	}
   885  
   886  fimm:
   887  	'$' LFCONST
   888  	{
   889  		$$ = nullgen;
   890  		$$.Type = obj.TYPE_FCONST;
   891  		$$.Val = $2;
   892  	}
   893  |	'$' '-' LFCONST
   894  	{
   895  		$$ = nullgen;
   896  		$$.Type = obj.TYPE_FCONST;
   897  		$$.Val = -$3;
   898  	}
   899  
   900  imm:	'$' con
   901  	{
   902  		$$ = nullgen;
   903  		$$.Type = obj.TYPE_CONST;
   904  		$$.Offset = $2;
   905  	}
   906  
   907  sreg:
   908  	LREG
   909  |	LR '(' con ')'
   910  	{
   911  		if $$ < 0 || $$ >= NREG {
   912  			print("register value out of range\n")
   913  		}
   914  		$$ = REG_R0 + $3;
   915  	}
   916  
   917  regaddr:
   918  	'(' sreg ')'
   919  	{
   920  		$$ = nullgen;
   921  		$$.Type = obj.TYPE_MEM;
   922  		$$.Reg = int16($2);
   923  		$$.Offset = 0;
   924  	}
   925  |	'(' sreg '+' sreg ')'
   926  	{
   927  		$$ = nullgen;
   928  		$$.Type = obj.TYPE_MEM;
   929  		$$.Reg = int16($2);
   930  		$$.Scale = int16($4);
   931  		$$.Offset = 0;
   932  	}
   933  
   934  addr:
   935  	name
   936  |	con '(' sreg ')'
   937  	{
   938  		$$ = nullgen;
   939  		$$.Type = obj.TYPE_MEM;
   940  		$$.Reg = int16($3);
   941  		$$.Offset = $1;
   942  	}
   943  
   944  name:
   945  	con '(' pointer ')'
   946  	{
   947  		$$ = nullgen;
   948  		$$.Type = obj.TYPE_MEM;
   949  		$$.Name = int8($3);
   950  		$$.Sym = nil;
   951  		$$.Offset = $1;
   952  	}
   953  |	LNAME offset '(' pointer ')'
   954  	{
   955  		$$ = nullgen;
   956  		$$.Type = obj.TYPE_MEM;
   957  		$$.Name = int8($4);
   958  		$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
   959  		$$.Offset = $2;
   960  	}
   961  |	LNAME '<' '>' offset '(' LSB ')'
   962  	{
   963  		$$ = nullgen;
   964  		$$.Type = obj.TYPE_MEM;
   965  		$$.Name = obj.NAME_STATIC;
   966  		$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
   967  		$$.Offset = $4;
   968  	}
   969  
   970  comma:
   971  |	','
   972  
   973  offset:
   974  	{
   975  		$$ = 0;
   976  	}
   977  |	'+' con
   978  	{
   979  		$$ = $2;
   980  	}
   981  |	'-' con
   982  	{
   983  		$$ = -$2;
   984  	}
   985  
   986  pointer:
   987  	LSB
   988  |	LSP
   989  |	LFP
   990  
   991  con:
   992  	LCONST
   993  |	LVAR
   994  	{
   995  		$$ = $1.Value;
   996  	}
   997  |	'-' con
   998  	{
   999  		$$ = -$2;
  1000  	}
  1001  |	'+' con
  1002  	{
  1003  		$$ = $2;
  1004  	}
  1005  |	'~' con
  1006  	{
  1007  		$$ = ^$2;
  1008  	}
  1009  |	'(' expr ')'
  1010  	{
  1011  		$$ = $2;
  1012  	}
  1013  
  1014  expr:
  1015  	con
  1016  |	expr '+' expr
  1017  	{
  1018  		$$ = $1 + $3;
  1019  	}
  1020  |	expr '-' expr
  1021  	{
  1022  		$$ = $1 - $3;
  1023  	}
  1024  |	expr '*' expr
  1025  	{
  1026  		$$ = $1 * $3;
  1027  	}
  1028  |	expr '/' expr
  1029  	{
  1030  		$$ = $1 / $3;
  1031  	}
  1032  |	expr '%' expr
  1033  	{
  1034  		$$ = $1 % $3;
  1035  	}
  1036  |	expr '<' '<' expr
  1037  	{
  1038  		$$ = $1 << uint($4);
  1039  	}
  1040  |	expr '>' '>' expr
  1041  	{
  1042  		$$ = $1 >> uint($4);
  1043  	}
  1044  |	expr '&' expr
  1045  	{
  1046  		$$ = $1 & $3;
  1047  	}
  1048  |	expr '^' expr
  1049  	{
  1050  		$$ = $1 ^ $3;
  1051  	}
  1052  |	expr '|' expr
  1053  	{
  1054  		$$ = $1 | $3;
  1055  	}