github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/liblink/asm9.c (about)

     1  // cmd/9l/optab.c, cmd/9l/asmout.c 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  // Instruction layout.
    31  
    32  #include <u.h>
    33  #include <libc.h>
    34  #include <bio.h>
    35  #include <link.h>
    36  #include "../cmd/9l/9.out.h"
    37  #include "../runtime/stack.h"
    38  
    39  enum {
    40  	FuncAlign = 8,
    41  };
    42  
    43  enum {
    44  	r0iszero = 1,
    45  };
    46  
    47  typedef	struct	Optab	Optab;
    48  
    49  struct	Optab
    50  {
    51  	short	as;
    52  	uchar	a1;
    53  	uchar	a2;
    54  	uchar	a3;
    55  	uchar	a4;
    56  	char	type;
    57  	char	size;
    58  	char	param;
    59  };
    60  
    61  static Optab	optab[] = {
    62  	{ ATEXT,	C_LEXT,	C_NONE, C_NONE, 	C_LCON, 	 0, 0, 0 },
    63  	{ ATEXT,	C_LEXT,	C_REG, C_NONE, 	C_LCON, 	 0, 0, 0 },
    64  	{ ATEXT,	C_LEXT,	C_NONE, C_LCON, 	C_LCON, 	 0, 0, 0 },
    65  	{ ATEXT,	C_LEXT,	C_REG, C_LCON, 	C_LCON, 	 0, 0, 0 },
    66  	{ ATEXT,	C_ADDR,	C_NONE, C_NONE, 	C_LCON, 	 0, 0, 0 },
    67  	{ ATEXT,	C_ADDR,	C_REG, C_NONE, 	C_LCON, 	 0, 0, 0 },
    68  	{ ATEXT,	C_ADDR,	C_NONE, C_LCON, 	C_LCON, 	 0, 0, 0 },
    69  	{ ATEXT,	C_ADDR,	C_REG, C_LCON, 	C_LCON, 	 0, 0, 0 },
    70  
    71  	/* move register */
    72  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_REG,		 1, 4, 0 },
    73  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_REG,		12, 4, 0 },
    74  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_REG,		13, 4, 0 },
    75  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_REG,		 12, 4, 0 },
    76  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_REG,		 13, 4, 0 },
    77  
    78  	{ AADD,		C_REG,	C_REG, C_NONE, 	C_REG,		 2, 4, 0 },
    79  	{ AADD,		C_REG,	C_NONE, C_NONE, 	C_REG,		 2, 4, 0 },
    80  	{ AADD,		C_ADDCON,C_REG, C_NONE, 	C_REG,		 4, 4, 0 },
    81  	{ AADD,		C_ADDCON,C_NONE, C_NONE, C_REG,		 4, 4, 0 },
    82  	{ AADD,		C_UCON,	C_REG, C_NONE, 	C_REG,		20, 4, 0 },
    83  	{ AADD,		C_UCON,	C_NONE, C_NONE, 	C_REG,		20, 4, 0 },
    84  	{ AADD,		C_LCON,	C_REG, C_NONE, 	C_REG,		22, 12, 0 },
    85  	{ AADD,		C_LCON,	C_NONE, C_NONE, 	C_REG,		22, 12, 0 },
    86  
    87  	{ AADDC,	C_REG,	C_REG, C_NONE, 	C_REG,		 2, 4, 0 },
    88  	{ AADDC,	C_REG,	C_NONE, C_NONE, 	C_REG,		 2, 4, 0 },
    89  	{ AADDC,	C_ADDCON,C_REG, C_NONE, 	C_REG,		 4, 4, 0 },
    90  	{ AADDC,	C_ADDCON,C_NONE, C_NONE, C_REG,		 4, 4, 0 },
    91  	{ AADDC,	C_LCON,	C_REG, C_NONE, 	C_REG,		22, 12, 0 },
    92  	{ AADDC,	C_LCON,	C_NONE, C_NONE, 	C_REG,		22, 12, 0 },
    93  
    94  	{ AAND,		C_REG,	C_REG, C_NONE, 	C_REG,		6, 4, 0 },	/* logical, no literal */
    95  	{ AAND,		C_REG,	C_NONE, C_NONE, 	C_REG,		6, 4, 0 },
    96  	{ AANDCC,	C_REG,	C_REG, C_NONE, 	C_REG,		6, 4, 0 },
    97  	{ AANDCC,	C_REG,	C_NONE, C_NONE, 	C_REG,		6, 4, 0 },
    98  
    99  	{ AANDCC,	C_ANDCON,C_NONE, C_NONE, C_REG,		58, 4, 0 },
   100  	{ AANDCC,	C_ANDCON,C_REG, C_NONE, 	C_REG,		58, 4, 0 },
   101  	{ AANDCC,	C_UCON,	C_NONE, C_NONE, 	C_REG,		59, 4, 0 },
   102  	{ AANDCC,	C_UCON,	C_REG, C_NONE, 	C_REG,		59, 4, 0 },
   103  	{ AANDCC,	C_LCON,	C_NONE, C_NONE, 	C_REG,		23, 12, 0 },
   104  	{ AANDCC,	C_LCON,	C_REG, C_NONE, 	C_REG,		23, 12, 0 },
   105  
   106  	{ AMULLW,	C_REG,	C_REG, C_NONE, 	C_REG,		 2, 4, 0 },
   107  	{ AMULLW,	C_REG,	C_NONE, C_NONE, 	C_REG,		 2, 4, 0 },
   108  	{ AMULLW,	C_ADDCON,C_REG, C_NONE, 	C_REG,		 4, 4, 0 },
   109  	{ AMULLW,	C_ADDCON,C_NONE, C_NONE, C_REG,		 4, 4, 0 },
   110  	{ AMULLW,	C_ANDCON,C_REG, C_NONE, 	C_REG,		 4, 4, 0 },
   111  	{ AMULLW,	C_ANDCON,	C_NONE, C_NONE,	C_REG,	 4, 4, 0 },
   112  	{ AMULLW,	C_LCON,	C_REG,	C_NONE,	C_REG,		22, 12, 0},
   113  	{ AMULLW,	C_LCON,	C_NONE,	C_NONE,	C_REG,		22, 12, 0},
   114  
   115  	{ ASUBC,	C_REG,	C_REG, C_NONE, 	C_REG,		 10, 4, 0 },
   116  	{ ASUBC,	C_REG,	C_NONE, C_NONE, 	C_REG,		 10, 4, 0 },
   117  	{ ASUBC,	C_REG,	C_NONE, C_ADDCON, 	C_REG,	 27, 4, 0 },
   118  	{ ASUBC,	C_REG,	C_NONE,	C_LCON,	C_REG,		28, 12, 0},
   119  
   120  	{ AOR,		C_REG,	C_REG, C_NONE, 	C_REG,		6, 4, 0 },	/* logical, literal not cc (or/xor) */
   121  	{ AOR,		C_REG,	C_NONE, C_NONE, 	C_REG,		6, 4, 0 },
   122  	{ AOR,		C_ANDCON, C_NONE, C_NONE,  C_REG,	58, 4, 0 },
   123  	{ AOR,		C_ANDCON, C_REG, C_NONE,  C_REG,		58, 4, 0 },
   124  	{ AOR,		C_UCON, C_NONE, C_NONE,  C_REG,		59, 4, 0 },
   125  	{ AOR,		C_UCON, C_REG, C_NONE,  C_REG,		59, 4, 0 },
   126  	{ AOR,		C_LCON,	C_NONE, C_NONE, 	C_REG,		23, 12, 0 },
   127  	{ AOR,		C_LCON,	C_REG, C_NONE, 	C_REG,		23, 12, 0 },
   128  
   129  	{ ADIVW,	C_REG,	C_REG, C_NONE, 	C_REG,		 2, 4, 0 },	/* op r1[,r2],r3 */
   130  	{ ADIVW,	C_REG,	C_NONE, C_NONE, 	C_REG,		 2, 4, 0 },
   131  	{ ASUB,	C_REG,	C_REG, C_NONE, 	C_REG,		 10, 4, 0 },	/* op r2[,r1],r3 */
   132  	{ ASUB,	C_REG,	C_NONE, C_NONE, 	C_REG,		 10, 4, 0 },
   133  
   134  	{ ASLW,	C_REG,	C_NONE, C_NONE, 	C_REG,		 6, 4, 0 },
   135  	{ ASLW,	C_REG,	C_REG, C_NONE, 	C_REG,		 6, 4, 0 },
   136  	{ ASLD,	C_REG,	C_NONE, C_NONE, 	C_REG,		 6, 4, 0 },
   137  	{ ASLD,	C_REG,	C_REG, C_NONE, 	C_REG,		 6, 4, 0 },
   138  	{ ASLD,	C_SCON,	C_REG, C_NONE,	C_REG,		25, 4, 0 },
   139  	{ ASLD,	C_SCON,	C_NONE, C_NONE,	C_REG,		25, 4, 0 },
   140  	{ ASLW,	C_SCON,	C_REG, C_NONE, 	C_REG,		57, 4, 0 },
   141  	{ ASLW,	C_SCON,	C_NONE, C_NONE, 	C_REG,		57, 4, 0 },
   142  
   143  	{ ASRAW,	C_REG,	C_NONE, C_NONE, 	C_REG,		 6, 4, 0 },
   144  	{ ASRAW,	C_REG,	C_REG, C_NONE, 	C_REG,		 6, 4, 0 },
   145  	{ ASRAW,	C_SCON,	C_REG, C_NONE, 	C_REG,		56, 4, 0 },
   146  	{ ASRAW,	C_SCON,	C_NONE, C_NONE, 	C_REG,		56, 4, 0 },
   147  	{ ASRAD,	C_REG,	C_NONE, C_NONE, 	C_REG,		 6, 4, 0 },
   148  	{ ASRAD,	C_REG,	C_REG, C_NONE, 	C_REG,		 6, 4, 0 },
   149  	{ ASRAD,	C_SCON,	C_REG, C_NONE, 	C_REG,		56, 4, 0 },
   150  	{ ASRAD,	C_SCON,	C_NONE, C_NONE, 	C_REG,		56, 4, 0 },
   151  
   152  	{ ARLWMI,	C_SCON, C_REG, C_LCON, 	C_REG,		62, 4, 0 },
   153  	{ ARLWMI,	C_REG,	C_REG, C_LCON, 	C_REG,		63, 4, 0 },
   154  	{ ARLDMI,	C_SCON,	C_REG, C_LCON,	C_REG,		30, 4, 0 },
   155  
   156  	{ ARLDC,	C_SCON,	C_REG, C_LCON,	C_REG,		29, 4, 0 },
   157  	{ ARLDCL,	C_SCON,	C_REG, C_LCON,	C_REG,		29, 4, 0 },
   158  	{ ARLDCL,	C_REG,	C_REG,	C_LCON,	C_REG,		14, 4, 0 },
   159  	{ ARLDCL, C_REG,	C_NONE,	C_LCON,	C_REG,		14, 4, 0 },
   160  
   161  	{ AFADD,	C_FREG,	C_NONE, C_NONE, 	C_FREG,		 2, 4, 0 },
   162  	{ AFADD,	C_FREG,	C_REG, C_NONE, 	C_FREG,		 2, 4, 0 },
   163  	{ AFABS,	C_FREG,	C_NONE, C_NONE, 	C_FREG,		33, 4, 0 },
   164  	{ AFABS,	C_NONE,	C_NONE, C_NONE, 	C_FREG,		33, 4, 0 },
   165  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_FREG,		33, 4, 0 },
   166  
   167  	{ AFMADD,	C_FREG,	C_REG, C_FREG, 	C_FREG,		 34, 4, 0 },
   168  	{ AFMUL,	C_FREG,	C_NONE, C_NONE, 	C_FREG,		 32, 4, 0 },
   169  	{ AFMUL,	C_FREG,	C_REG, C_NONE, 	C_FREG,		 32, 4, 0 },
   170  
   171  	/* store, short offset */
   172  	{ AMOVD,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   173  	{ AMOVW,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   174  	{ AMOVWZ,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   175  	{ AMOVBZ,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   176  	{ AMOVBZU,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   177  	{ AMOVB,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   178  	{ AMOVBU,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	 7, 4, REGZERO },
   179  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_SEXT,		 7, 4, REGSB },
   180  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_SEXT,		 7, 4, REGSB },
   181  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_SEXT,		 7, 4, REGSB },
   182  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_SEXT,		 7, 4, REGSB },
   183  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_SEXT,		 7, 4, REGSB },
   184  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_SAUTO,	 7, 4, REGSP },
   185  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_SAUTO,	 7, 4, REGSP },
   186  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_SAUTO,	 7, 4, REGSP },
   187  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_SAUTO,	 7, 4, REGSP },
   188  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_SAUTO,	 7, 4, REGSP },
   189  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   190  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   191  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   192  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   193  	{ AMOVBZU,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   194  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   195  	{ AMOVBU,	C_REG,	C_NONE, C_NONE, 	C_SOREG,	 7, 4, REGZERO },
   196  
   197  	/* load, short offset */
   198  	{ AMOVD,	C_ZOREG,C_REG, C_NONE, 	C_REG,		 8, 4, REGZERO },
   199  	{ AMOVW,	C_ZOREG,C_REG, C_NONE, 	C_REG,		 8, 4, REGZERO },
   200  	{ AMOVWZ,	C_ZOREG,C_REG, C_NONE, 	C_REG,		 8, 4, REGZERO },
   201  	{ AMOVBZ,	C_ZOREG,C_REG, C_NONE, 	C_REG,		 8, 4, REGZERO },
   202  	{ AMOVBZU,	C_ZOREG,C_REG, C_NONE, 	C_REG,		 8, 4, REGZERO },
   203  	{ AMOVB,	C_ZOREG,C_REG, C_NONE, 	C_REG,		9, 8, REGZERO },
   204  	{ AMOVBU,	C_ZOREG,C_REG, C_NONE, 	C_REG,		9, 8, REGZERO },
   205  	{ AMOVD,	C_SEXT,	C_NONE, C_NONE, 	C_REG,		 8, 4, REGSB },
   206  	{ AMOVW,	C_SEXT,	C_NONE, C_NONE, 	C_REG,		 8, 4, REGSB },
   207  	{ AMOVWZ,	C_SEXT,	C_NONE, C_NONE, 	C_REG,		 8, 4, REGSB },
   208  	{ AMOVBZ,	C_SEXT,	C_NONE, C_NONE, 	C_REG,		 8, 4, REGSB },
   209  	{ AMOVB,	C_SEXT,	C_NONE, C_NONE, 	C_REG,		9, 8, REGSB },
   210  	{ AMOVD,	C_SAUTO,C_NONE, C_NONE, 	C_REG,		 8, 4, REGSP },
   211  	{ AMOVW,	C_SAUTO,C_NONE, C_NONE, 	C_REG,		 8, 4, REGSP },
   212  	{ AMOVWZ,	C_SAUTO,C_NONE, C_NONE, 	C_REG,		 8, 4, REGSP },
   213  	{ AMOVBZ,	C_SAUTO,C_NONE, C_NONE, 	C_REG,		 8, 4, REGSP },
   214  	{ AMOVB,	C_SAUTO,C_NONE, C_NONE, 	C_REG,		9, 8, REGSP },
   215  	{ AMOVD,	C_SOREG,C_NONE, C_NONE, 	C_REG,		 8, 4, REGZERO },
   216  	{ AMOVW,	C_SOREG,C_NONE, C_NONE, 	C_REG,		 8, 4, REGZERO },
   217  	{ AMOVWZ,	C_SOREG,C_NONE, C_NONE, 	C_REG,		 8, 4, REGZERO },
   218  	{ AMOVBZ,	C_SOREG,C_NONE, C_NONE, 	C_REG,		 8, 4, REGZERO },
   219  	{ AMOVBZU,	C_SOREG,C_NONE, C_NONE, 	C_REG,		 8, 4, REGZERO },
   220  	{ AMOVB,	C_SOREG,C_NONE, C_NONE, 	C_REG,		9, 8, REGZERO },
   221  	{ AMOVBU,	C_SOREG,C_NONE, C_NONE, 	C_REG,		9, 8, REGZERO },
   222  
   223  	/* store, long offset */
   224  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   225  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   226  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   227  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   228  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   229  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   230  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   231  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   232  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   233  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   234  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   235  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   236  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   237  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   238  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   239  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   240  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   241  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   242  	{ AMOVBZ,	C_REG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   243  	{ AMOVB,	C_REG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   244  
   245  	/* load, long offset */
   246  	{ AMOVD,	C_LEXT,	C_NONE, C_NONE, 	C_REG,		36, 8, REGSB },
   247  	{ AMOVW,	C_LEXT,	C_NONE, C_NONE, 	C_REG,		36, 8, REGSB },
   248  	{ AMOVWZ,	C_LEXT,	C_NONE, C_NONE, 	C_REG,		36, 8, REGSB },
   249  	{ AMOVBZ,	C_LEXT,	C_NONE, C_NONE, 	C_REG,		36, 8, REGSB },
   250  	{ AMOVB,	C_LEXT,	C_NONE, C_NONE, 	C_REG,		37, 12, REGSB },
   251  	{ AMOVD,	C_LAUTO,C_NONE, C_NONE, 	C_REG,		36, 8, REGSP },
   252  	{ AMOVW,	C_LAUTO,C_NONE, C_NONE, 	C_REG,		36, 8, REGSP },
   253  	{ AMOVWZ,	C_LAUTO,C_NONE, C_NONE, 	C_REG,		36, 8, REGSP },
   254  	{ AMOVBZ,	C_LAUTO,C_NONE, C_NONE, 	C_REG,		36, 8, REGSP },
   255  	{ AMOVB,	C_LAUTO,C_NONE, C_NONE, 	C_REG,		37, 12, REGSP },
   256  	{ AMOVD,	C_LOREG,C_NONE, C_NONE, 	C_REG,		36, 8, REGZERO },
   257  	{ AMOVW,	C_LOREG,C_NONE, C_NONE, 	C_REG,		36, 8, REGZERO },
   258  	{ AMOVWZ,	C_LOREG,C_NONE, C_NONE, 	C_REG,		36, 8, REGZERO },
   259  	{ AMOVBZ,	C_LOREG,C_NONE, C_NONE, 	C_REG,		36, 8, REGZERO },
   260  	{ AMOVB,	C_LOREG,C_NONE, C_NONE, 	C_REG,		37, 12, REGZERO },
   261  	{ AMOVD,	C_ADDR,	C_NONE, C_NONE, 	C_REG,		75, 8, 0 },
   262  	{ AMOVW,	C_ADDR,	C_NONE, C_NONE, 	C_REG,		75, 8, 0 },
   263  	{ AMOVWZ,	C_ADDR,	C_NONE, C_NONE, 	C_REG,		75, 8, 0 },
   264  	{ AMOVBZ,	C_ADDR,	C_NONE, C_NONE, 	C_REG,		75, 8, 0 },
   265  	{ AMOVB,	C_ADDR,	C_NONE, C_NONE, 	C_REG,		76, 12, 0 },
   266  
   267  	/* load constant */
   268  	{ AMOVD,	C_SECON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSB },
   269  	{ AMOVD,	C_SACON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSP },
   270  	{ AMOVD,	C_LECON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSB }, 
   271  	{ AMOVD,	C_LACON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSP },
   272  	{ AMOVD,	C_ADDCON,C_NONE, C_NONE, C_REG,		 3, 4, REGZERO },
   273  	{ AMOVW,	C_SECON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSB },	/* TO DO: check */
   274  	{ AMOVW,	C_SACON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSP },
   275  	{ AMOVW,	C_LECON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSB }, 
   276  	{ AMOVW,	C_LACON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSP },
   277  	{ AMOVW,	C_ADDCON,C_NONE, C_NONE, C_REG,		 3, 4, REGZERO },
   278  	{ AMOVWZ,	C_SECON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSB },	/* TO DO: check */
   279  	{ AMOVWZ,	C_SACON,C_NONE, C_NONE, 	C_REG,		 3, 4, REGSP },
   280  	{ AMOVWZ,	C_LECON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSB }, 
   281  	{ AMOVWZ,	C_LACON,C_NONE, C_NONE, 	C_REG,		26, 8, REGSP },
   282  	{ AMOVWZ,	C_ADDCON,C_NONE, C_NONE, C_REG,		 3, 4, REGZERO },
   283  
   284  	/* load unsigned/long constants (TO DO: check) */
   285  	{ AMOVD,	C_UCON, C_NONE, C_NONE,  C_REG,		3, 4, REGZERO },
   286  	{ AMOVD,	C_LCON,	C_NONE, C_NONE, 	C_REG,		19, 8, 0 },
   287  	{ AMOVW,	C_UCON, C_NONE, C_NONE,  C_REG,		3, 4, REGZERO },
   288  	{ AMOVW,	C_LCON,	C_NONE, C_NONE, 	C_REG,		19, 8, 0 },
   289  	{ AMOVWZ,	C_UCON, C_NONE, C_NONE,  C_REG,		3, 4, REGZERO },
   290  	{ AMOVWZ,	C_LCON,	C_NONE, C_NONE, 	C_REG,		19, 8, 0 },
   291  
   292  	{ AMOVHBR,	C_ZOREG,	C_REG, C_NONE, C_REG,		45, 4, 0 },
   293  	{ AMOVHBR,	C_ZOREG, C_NONE, C_NONE, C_REG,	45, 4, 0 },
   294  	{ AMOVHBR,	C_REG,	C_REG, C_NONE,	C_ZOREG,		44, 4, 0 },
   295  	{ AMOVHBR,	C_REG,	C_NONE, C_NONE,	C_ZOREG,		44, 4, 0 },
   296  
   297  	{ ASYSCALL,	C_NONE,	C_NONE, C_NONE, 	C_NONE,		 5, 4, 0 },
   298  	{ ASYSCALL,	C_REG,	C_NONE, C_NONE, 	C_NONE,		 77, 12, 0 },
   299  	{ ASYSCALL,	C_SCON,	C_NONE, C_NONE, 	C_NONE,		 77, 12, 0 },
   300  
   301  	{ ABEQ,		C_NONE,	C_NONE, C_NONE, 	C_SBRA,		16, 4, 0 },
   302  	{ ABEQ,		C_CREG,	C_NONE, C_NONE, 	C_SBRA,		16, 4, 0 },
   303  
   304  	{ ABR,		C_NONE,	C_NONE, C_NONE, 	C_LBRA,		11, 4, 0 },
   305  
   306  	{ ABC,		C_SCON,	C_REG, C_NONE, 	C_SBRA,		16, 4, 0 },
   307  	{ ABC,		C_SCON, C_REG, C_NONE, 	C_LBRA,		17, 4, 0 },
   308  
   309  	{ ABR,		C_NONE,	C_NONE, C_NONE, 	C_LR,		18, 4, 0 },
   310  	{ ABR,		C_NONE,	C_NONE, C_NONE, 	C_CTR,		18, 4, 0 },
   311  	{ ABR,		C_REG,	C_NONE, C_NONE, 	C_CTR,		18, 4, 0 },
   312  	{ ABR,		C_NONE,	C_NONE, C_NONE, 	C_ZOREG,		15, 8, 0 },
   313  
   314  	{ ABC,		C_NONE,	C_REG, C_NONE, 	C_LR,		18, 4, 0 },
   315  	{ ABC,		C_NONE,	C_REG, C_NONE, 	C_CTR,		18, 4, 0 },
   316  	{ ABC,		C_SCON,	C_REG, C_NONE, 	C_LR,		18, 4, 0 },
   317  	{ ABC,		C_SCON,	C_REG, C_NONE, 	C_CTR,		18, 4, 0 },
   318  	{ ABC,		C_NONE,	C_NONE, C_NONE, 	C_ZOREG,		15, 8, 0 },
   319  
   320  	{ AFMOVD,	C_SEXT,	C_NONE, C_NONE, 	C_FREG,		8, 4, REGSB },
   321  	{ AFMOVD,	C_SAUTO,C_NONE, C_NONE, 	C_FREG,		8, 4, REGSP },
   322  	{ AFMOVD,	C_SOREG,C_NONE, C_NONE, 	C_FREG,		8, 4, REGZERO },
   323  
   324  	{ AFMOVD,	C_LEXT,	C_NONE, C_NONE, 	C_FREG,		36, 8, REGSB },
   325  	{ AFMOVD,	C_LAUTO,C_NONE, C_NONE, 	C_FREG,		36, 8, REGSP },
   326  	{ AFMOVD,	C_LOREG,C_NONE, C_NONE, 	C_FREG,		36, 8, REGZERO },
   327  	{ AFMOVD,	C_ADDR,	C_NONE, C_NONE, 	C_FREG,		75, 8, 0 },
   328  
   329  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_SEXT,		7, 4, REGSB },
   330  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_SAUTO,	7, 4, REGSP },
   331  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_SOREG,	7, 4, REGZERO },
   332  
   333  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_LEXT,		35, 8, REGSB },
   334  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_LAUTO,	35, 8, REGSP },
   335  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_LOREG,	35, 8, REGZERO },
   336  	{ AFMOVD,	C_FREG,	C_NONE, C_NONE, 	C_ADDR,		74, 8, 0 },
   337  
   338  	{ ASYNC,		C_NONE,	C_NONE, C_NONE, 	C_NONE,		46, 4, 0 },
   339  	{ AWORD,	C_LCON,	C_NONE, C_NONE, 	C_NONE,		40, 4, 0 },
   340  	{ ADWORD,	C_LCON,	C_NONE, C_NONE, C_NONE,	31, 8, 0 },
   341  	{ ADWORD,	C_DCON,	C_NONE, C_NONE, C_NONE,	31, 8, 0 },
   342  
   343  	{ AADDME,	C_REG,	C_NONE, C_NONE, 	C_REG,		47, 4, 0 },
   344  
   345  	{ AEXTSB,	C_REG,	C_NONE, C_NONE, 	C_REG,		48, 4, 0 },
   346  	{ AEXTSB,	C_NONE,	C_NONE, C_NONE, 	C_REG,		48, 4, 0 },
   347  
   348  	{ ANEG,		C_REG,	C_NONE, C_NONE, 	C_REG,		47, 4, 0 },
   349  	{ ANEG,		C_NONE,	C_NONE, C_NONE, 	C_REG,		47, 4, 0 },
   350  
   351  	{ AREM,		C_REG,	C_NONE, C_NONE, 	C_REG,		50, 12, 0 },
   352  	{ AREM,		C_REG,	C_REG, C_NONE, 	C_REG,		50, 12, 0 },
   353  	{ AREMU,		C_REG,	C_NONE, C_NONE, 	C_REG,		50, 16, 0 },
   354  	{ AREMU,		C_REG,	C_REG, C_NONE, 	C_REG,		50, 16, 0 },
   355  	{ AREMD,		C_REG,	C_NONE, C_NONE, 	C_REG,		51, 12, 0 },
   356  	{ AREMD,		C_REG,	C_REG, C_NONE, 	C_REG,		51, 12, 0 },
   357  	{ AREMDU,		C_REG,	C_NONE, C_NONE, 	C_REG,		51, 12, 0 },
   358  	{ AREMDU,		C_REG,	C_REG, C_NONE, 	C_REG,		51, 12, 0 },
   359  
   360  	{ AMTFSB0,	C_SCON,	C_NONE, C_NONE, 	C_NONE,		52, 4, 0 },
   361  	{ AMOVFL, C_FPSCR, C_NONE, C_NONE,	C_FREG,		53, 4, 0 },
   362  	{ AMOVFL, C_FREG, C_NONE, C_NONE,	C_FPSCR,		64, 4, 0 },
   363  	{ AMOVFL, C_FREG, C_NONE, C_LCON,	C_FPSCR,		64, 4, 0 },
   364  	{ AMOVFL,	C_LCON, C_NONE, C_NONE,	C_FPSCR,		65, 4, 0 },
   365  
   366  	{ AMOVD,	C_MSR,	C_NONE, C_NONE, 	C_REG,		54, 4, 0 },		/* mfmsr */
   367  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_MSR,		54, 4, 0 },		/* mtmsrd */
   368  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_MSR,		54, 4, 0 },		/* mtmsr */
   369  
   370  	/* 64-bit special registers */
   371  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_SPR,		66, 4, 0 },
   372  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_LR,		66, 4, 0 },
   373  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_CTR,		66, 4, 0 },
   374  	{ AMOVD,	C_REG,	C_NONE, C_NONE, 	C_XER,		66, 4, 0 },
   375  	{ AMOVD,	C_SPR,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   376  	{ AMOVD,	C_LR,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   377  	{ AMOVD,	C_CTR,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   378  	{ AMOVD,	C_XER,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   379  
   380  	/* 32-bit special registers (gloss over sign-extension or not?) */
   381  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_SPR,		66, 4, 0 },
   382  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_CTR,		66, 4, 0 },
   383  	{ AMOVW,	C_REG,	C_NONE, C_NONE, 	C_XER,		66, 4, 0 },
   384  	{ AMOVW,	C_SPR,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   385  	{ AMOVW,	C_XER,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   386  
   387  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_SPR,		66, 4, 0 },
   388  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_CTR,		66, 4, 0 },
   389  	{ AMOVWZ,	C_REG,	C_NONE, C_NONE, 	C_XER,		66, 4, 0 },
   390  	{ AMOVWZ,	C_SPR,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   391  	{ AMOVWZ,	C_XER,	C_NONE, C_NONE, 	C_REG,		66, 4, 0 },
   392  
   393  	{ AMOVFL,	C_FPSCR, C_NONE, C_NONE, 	C_CREG,		73, 4, 0 },
   394  	{ AMOVFL,	C_CREG,	C_NONE, C_NONE, 	C_CREG,		67, 4, 0 },
   395  	{ AMOVW,	C_CREG,	C_NONE,	C_NONE,		C_REG,		68, 4, 0 },
   396  	{ AMOVWZ,	C_CREG,	C_NONE,	C_NONE,		C_REG,		68, 4, 0 },
   397  	{ AMOVFL,	C_REG, C_NONE, C_LCON, C_CREG,		69, 4, 0 },
   398  	{ AMOVFL,	C_REG, C_NONE, C_NONE, C_CREG,		69, 4, 0 },
   399  	{ AMOVW,	C_REG, C_NONE, C_NONE, C_CREG,		69, 4, 0 },
   400  	{ AMOVWZ,	C_REG, C_NONE, C_NONE, C_CREG,		69, 4, 0 },
   401  
   402  	{ ACMP,	C_REG,	C_NONE, C_NONE, 	C_REG,	70, 4, 0 },
   403  	{ ACMP,	C_REG,	C_REG, C_NONE, 	C_REG,	70, 4, 0 },
   404  	{ ACMP,	C_REG,	C_NONE, C_NONE,	C_ADDCON,	71, 4, 0 },
   405  	{ ACMP,	C_REG,	C_REG, C_NONE,	C_ADDCON,	71, 4, 0 },
   406  
   407  	{ ACMPU,	C_REG,	C_NONE, C_NONE, 	C_REG,	70, 4, 0 },
   408  	{ ACMPU,	C_REG,	C_REG, C_NONE, 	C_REG,	70, 4, 0 },
   409  	{ ACMPU,	C_REG,	C_NONE, C_NONE,	C_ANDCON,	71, 4, 0 },
   410  	{ ACMPU,	C_REG,	C_REG, C_NONE,	C_ANDCON,	71, 4, 0 },
   411  
   412  	{ AFCMPO,	C_FREG,	C_NONE, C_NONE, 	C_FREG,	70, 4, 0 },
   413  	{ AFCMPO,	C_FREG,	C_REG, C_NONE, 	C_FREG,	70, 4, 0 },
   414  
   415  	{ ATW,		C_LCON,	C_REG, C_NONE, 	C_REG,		60, 4, 0 },
   416  	{ ATW,		C_LCON,	C_REG, C_NONE, 	C_ADDCON,	61, 4, 0 },
   417  
   418  	{ ADCBF,	C_ZOREG, C_NONE, C_NONE,  C_NONE,	43, 4, 0 },
   419  	{ ADCBF,	C_ZOREG, C_REG, C_NONE,  C_NONE,	43, 4, 0 },
   420  
   421  	{ AECOWX,	C_REG,	C_REG, C_NONE, 	C_ZOREG,	44, 4, 0 },
   422  	{ AECIWX,	C_ZOREG, C_REG, C_NONE,  C_REG,		45, 4, 0 },
   423  	{ AECOWX,	C_REG,	C_NONE, C_NONE, 	C_ZOREG,	44, 4, 0 },
   424  	{ AECIWX,	C_ZOREG, C_NONE, C_NONE,  C_REG,		45, 4, 0 },
   425  
   426  	{ AEIEIO,	C_NONE,	C_NONE, C_NONE, 	C_NONE,		46, 4, 0 },
   427  	{ ATLBIE,	C_REG, C_NONE, C_NONE,		C_NONE,		49, 4, 0 },
   428  	{ ATLBIE,	C_SCON, C_NONE, C_NONE,	C_REG,	49, 4, 0 },
   429  	{ ASLBMFEE, C_REG, C_NONE, C_NONE,	C_REG,	55, 4, 0 },
   430  	{ ASLBMTE, C_REG, C_NONE, C_NONE,	C_REG,	55, 4, 0 },
   431  
   432  	{ ASTSW,	C_REG,	C_NONE, C_NONE, 	C_ZOREG,	44, 4, 0 },
   433  	{ ASTSW,	C_REG,	C_NONE, C_LCON, 	C_ZOREG,	41, 4, 0 },
   434  	{ ALSW,	C_ZOREG, C_NONE, C_NONE,  C_REG,		45, 4, 0 },
   435  	{ ALSW,	C_ZOREG, C_NONE, C_LCON,  C_REG,		42, 4, 0 },
   436  
   437  	{ AUNDEF,	C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0 },
   438  	{ AUSEFIELD,	C_ADDR,	C_NONE,	C_NONE, C_NONE,	0, 0, 0 },
   439  	{ APCDATA,	C_LCON,	C_NONE,	C_NONE, C_LCON,	0, 0, 0 },
   440  	{ AFUNCDATA,	C_SCON,	C_NONE,	C_NONE, C_ADDR,	0, 0, 0 },
   441  	{ ANOP,		C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
   442  
   443  	{ ADUFFZERO,	C_NONE,	C_NONE, C_NONE,	C_LBRA,	11, 4, 0 },  // same as ABR/ABL
   444  	{ ADUFFCOPY,	C_NONE,	C_NONE, C_NONE,	C_LBRA,	11, 4, 0 },  // same as ABR/ABL
   445  
   446  	{ AXXX,		C_NONE,	C_NONE, C_NONE, 	C_NONE,		 0, 4, 0 },
   447  };
   448  
   449  static int ocmp(const void *, const void *);
   450  static int cmp(int, int);
   451  static void buildop(Link*);
   452  static void prasm(Prog *);
   453  static int isint32(vlong);
   454  static int isuint32(uvlong);
   455  static int aclass(Link*, Addr*);
   456  static Optab* oplook(Link*, Prog*);
   457  static void asmout(Link*, Prog*, Optab*, int32*);
   458  static vlong vregoff(Link*, Addr*);
   459  static int32 regoff(Link*, Addr*);
   460  static int32 oprrr(Link*, int);
   461  static int32 opirr(Link*, int);
   462  static int32 opload(Link*, int);
   463  static int32 opstore(Link*, int);
   464  static int32 oploadx(Link*, int);
   465  static int32 opstorex(Link*, int);
   466  static int getmask(uchar*, uint32);
   467  static void maskgen(Link*, Prog*, uchar*, uint32);
   468  static int getmask64(uchar*, uvlong);
   469  static void maskgen64(Link*, Prog*, uchar*, uvlong);
   470  static uint32 loadu32(int, vlong);
   471  static void addaddrreloc(Link*, LSym*, int*, int*);
   472  
   473  static struct
   474  {
   475  	Optab*	start;
   476  	Optab*	stop;
   477  } oprange[ALAST];
   478  
   479  static uchar	xcmp[C_NCLASS][C_NCLASS];
   480  
   481  
   482  void
   483  span9(Link *ctxt, LSym *cursym)
   484  {
   485  	Prog *p, *q;
   486  	Optab *o;
   487  	int m, bflag;
   488  	vlong c, otxt;
   489  	int32 out[6], i, j;
   490  	uchar *bp, *cast;
   491  
   492  	p = cursym->text;
   493  	if(p == nil || p->link == nil) // handle external functions and ELF section symbols
   494  		return;
   495  	ctxt->cursym = cursym;
   496  	ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8;
   497  
   498  	if(oprange[AANDN].start == nil)
   499   		buildop(ctxt);
   500  
   501  	c = 0;	
   502  	p->pc = c;
   503  
   504  	for(p = p->link; p != nil; p = p->link) {
   505  		ctxt->curp = p;
   506  		p->pc = c;
   507  		o = oplook(ctxt, p);
   508  		m = o->size;
   509  		if(m == 0) {
   510  			if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
   511  				ctxt->diag("zero-width instruction\n%P", p);
   512  			continue;
   513  		}
   514  		c += m;
   515  	}
   516  	cursym->size = c;
   517  
   518  	/*
   519  	 * if any procedure is large enough to
   520  	 * generate a large SBRA branch, then
   521  	 * generate extra passes putting branches
   522  	 * around jmps to fix. this is rare.
   523  	 */
   524  	bflag = 1;
   525  	while(bflag) {
   526  		if(ctxt->debugvlog)
   527  			Bprint(ctxt->bso, "%5.2f span1\n", cputime());
   528  		bflag = 0;
   529  		c = 0;
   530  		for(p = cursym->text->link; p != nil; p = p->link) {
   531  			p->pc = c;
   532  			o = oplook(ctxt, p);
   533  
   534  			// very large conditional branches
   535  			if((o->type == 16 || o->type == 17) && p->pcond) {
   536  				otxt = p->pcond->pc - c;
   537  				if(otxt < -(1L<<15)+10 || otxt >= (1L<<15)-10) {
   538  					q = ctxt->arch->prg();
   539  					q->link = p->link;
   540  					p->link = q;
   541  					q->as = ABR;
   542  					q->to.type = D_BRANCH;
   543  					q->pcond = p->pcond;
   544  					p->pcond = q;
   545  					q = ctxt->arch->prg();
   546  					q->link = p->link;
   547  					p->link = q;
   548  					q->as = ABR;
   549  					q->to.type = D_BRANCH;
   550  					q->pcond = q->link->link;
   551  					//addnop(p->link);
   552  					//addnop(p);
   553  					bflag = 1;
   554  				}
   555  			}
   556  
   557  			m = o->size;
   558  			if(m == 0) {
   559  				if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
   560  					ctxt->diag("zero-width instruction\n%P", p);
   561  				continue;
   562  			}
   563  			c += m;
   564  		}
   565  		cursym->size = c;
   566  	}
   567  
   568  	c += -c&(FuncAlign-1);
   569  	cursym->size = c;
   570  
   571  	/*
   572  	 * lay out the code, emitting code and data relocations.
   573  	 */
   574  	if(ctxt->tlsg == nil)
   575  		ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
   576  
   577  	symgrow(ctxt, cursym, cursym->size);
   578  
   579  	bp = cursym->p;
   580  	for(p = cursym->text->link; p != nil; p = p->link) {
   581  		ctxt->pc = p->pc;
   582  		ctxt->curp = p;
   583  		o = oplook(ctxt, p);
   584  		if(o->size > 4*nelem(out))
   585  			sysfatal("out array in span9 is too small, need at least %d for %P", o->size/4, p);
   586  		asmout(ctxt, p, o, out);
   587  		for(i=0; i<o->size/4; i++) {
   588  			cast = (uchar*)&out[i];
   589  			for(j=0; j<4; j++)
   590  				*bp++ = cast[inuxi4[j]];
   591  		}
   592  	}
   593  }
   594  
   595  static int
   596  isint32(vlong v)
   597  {
   598  	return (int32)v == v;
   599  }
   600  
   601  static int
   602  isuint32(uvlong v)
   603  {
   604  	return (uint32)v == v;
   605  }
   606  
   607  static int
   608  aclass(Link *ctxt, Addr *a)
   609  {
   610  	LSym *s;
   611  
   612  	switch(a->type) {
   613  	case D_NONE:
   614  		return C_NONE;
   615  
   616  	case D_REG:
   617  		return C_REG;
   618  
   619  	case D_FREG:
   620  		return C_FREG;
   621  
   622  	case D_CREG:
   623  		return C_CREG;
   624  
   625  	case D_SPR:
   626  		if(a->offset == D_LR)
   627  			return C_LR;
   628  		if(a->offset == D_XER)
   629  			return C_XER;
   630  		if(a->offset == D_CTR)
   631  			return C_CTR;
   632  		return C_SPR;
   633  
   634  	case D_DCR:
   635  		return C_SPR;
   636  
   637  	case D_FPSCR:
   638  		return C_FPSCR;
   639  
   640  	case D_MSR:
   641  		return C_MSR;
   642  
   643  	case D_OREG:
   644  		switch(a->name) {
   645  		case D_EXTERN:
   646  		case D_STATIC:
   647  			if(a->sym == nil)
   648  				break;
   649  			ctxt->instoffset = a->offset;
   650  			if(a->sym != nil) // use relocation
   651  				return C_ADDR;
   652  			return C_LEXT;
   653  		case D_AUTO:
   654  			ctxt->instoffset = ctxt->autosize + a->offset;
   655  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   656  				return C_SAUTO;
   657  			return C_LAUTO;
   658  		case D_PARAM:
   659  			ctxt->instoffset = ctxt->autosize + a->offset + 8L;
   660  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   661  				return C_SAUTO;
   662  			return C_LAUTO;
   663  		case D_NONE:
   664  			ctxt->instoffset = a->offset;
   665  			if(ctxt->instoffset == 0)
   666  				return C_ZOREG;
   667  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   668  				return C_SOREG;
   669  			return C_LOREG;
   670  		}
   671  		return C_GOK;
   672  
   673  	case D_OPT:
   674  		ctxt->instoffset = a->offset & 31L;
   675  		if(a->name == D_NONE)
   676  			return C_SCON;
   677  		return C_GOK;
   678  
   679  	case D_CONST:
   680  		switch(a->name) {
   681  		case D_NONE:
   682  			ctxt->instoffset = a->offset;
   683  			if(a->reg != NREG) {
   684  				if(-BIG <= ctxt->instoffset && ctxt->instoffset <= BIG)
   685  					return C_SACON;
   686  				return C_LACON;
   687  			}
   688  		consize:
   689  			if(ctxt->instoffset >= 0) {
   690  				if(ctxt->instoffset == 0)
   691  					return C_ZCON;
   692  				if(ctxt->instoffset <= 0x7fff)
   693  					return C_SCON;
   694  				if(ctxt->instoffset <= 0xffff)
   695  					return C_ANDCON;
   696  				if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset))	/* && (instoffset & (1<<31)) == 0) */
   697  					return C_UCON;
   698  				if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset))
   699  					return C_LCON;
   700  				return C_DCON;
   701  			}
   702  			if(ctxt->instoffset >= -0x8000)
   703  				return C_ADDCON;
   704  			if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset))
   705  				return C_UCON;
   706  			if(isint32(ctxt->instoffset))
   707  				return C_LCON;
   708  			return C_DCON;
   709  
   710  		case D_EXTERN:
   711  		case D_STATIC:
   712  			s = a->sym;
   713  			if(s == nil)
   714  				break;
   715  			if(s->type == SCONST) {
   716  				ctxt->instoffset = s->value + a->offset;
   717  				goto consize;
   718  			}
   719  			ctxt->instoffset = s->value + a->offset;
   720  			/* not sure why this barfs */
   721  			return C_LCON;
   722  
   723  		case D_AUTO:
   724  			ctxt->instoffset = ctxt->autosize + a->offset;
   725  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   726  				return C_SACON;
   727  			return C_LACON;
   728  
   729  		case D_PARAM:
   730  			ctxt->instoffset = ctxt->autosize + a->offset + 8L;
   731  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   732  				return C_SACON;
   733  			return C_LACON;
   734  		}
   735  		return C_GOK;
   736  
   737  	case D_BRANCH:
   738  		return C_SBRA;
   739  	}
   740  	return C_GOK;
   741  }
   742  
   743  static void
   744  prasm(Prog *p)
   745  {
   746  	print("%P\n", p);
   747  }
   748  
   749  static Optab*
   750  oplook(Link *ctxt, Prog *p)
   751  {
   752  	int a1, a2, a3, a4, r;
   753  	uchar *c1, *c3, *c4;
   754  	Optab *o, *e;
   755  
   756  	a1 = p->optab;
   757  	if(a1)
   758  		return optab+(a1-1);
   759  	a1 = p->from.class;
   760  	if(a1 == 0) {
   761  		a1 = aclass(ctxt, &p->from) + 1;
   762  		p->from.class = a1;
   763  	}
   764  	a1--;
   765  	a3 = p->from3.class;
   766  	if(a3 == 0) {
   767  		a3 = aclass(ctxt, &p->from3) + 1;
   768  		p->from3.class = a3;
   769  	}
   770  	a3--;
   771  	a4 = p->to.class;
   772  	if(a4 == 0) {
   773  		a4 = aclass(ctxt, &p->to) + 1;
   774  		p->to.class = a4;
   775  	}
   776  	a4--;
   777  	a2 = C_NONE;
   778  	if(p->reg != NREG)
   779  		a2 = C_REG;
   780  //print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
   781  	r = p->as;
   782  	o = oprange[r].start;
   783  	if(o == 0)
   784  		o = oprange[r].stop; /* just generate an error */
   785  	e = oprange[r].stop;
   786  	c1 = xcmp[a1];
   787  	c3 = xcmp[a3];
   788  	c4 = xcmp[a4];
   789  	for(; o<e; o++)
   790  		if(o->a2 == a2)
   791  		if(c1[o->a1])
   792  		if(c3[o->a3])
   793  		if(c4[o->a4]) {
   794  			p->optab = (o-optab)+1;
   795  			return o;
   796  		}
   797  	ctxt->diag("illegal combination %A %^ %^ %^ %^",
   798  		p->as, a1, a2, a3, a4);
   799  	prasm(p);
   800  	if(o == 0)
   801  		o = optab;
   802  	return o;
   803  }
   804  
   805  static int
   806  cmp(int a, int b)
   807  {
   808  
   809  	if(a == b)
   810  		return 1;
   811  	switch(a) {
   812  	case C_LCON:
   813  		if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON)
   814  			return 1;
   815  		break;
   816  	case C_ADDCON:
   817  		if(b == C_ZCON || b == C_SCON)
   818  			return 1;
   819  		break;
   820  	case C_ANDCON:
   821  		if(b == C_ZCON || b == C_SCON)
   822  			return 1;
   823  		break;
   824  	case C_SPR:
   825  		if(b == C_LR || b == C_XER || b == C_CTR)
   826  			return 1;
   827  		break;
   828  	case C_UCON:
   829  		if(b == C_ZCON)
   830  			return 1;
   831  		break;
   832  	case C_SCON:
   833  		if(b == C_ZCON)
   834  			return 1;
   835  		break;
   836  	case C_LACON:
   837  		if(b == C_SACON)
   838  			return 1;
   839  		break;
   840  	case C_LBRA:
   841  		if(b == C_SBRA)
   842  			return 1;
   843  		break;
   844  	case C_LEXT:
   845  		if(b == C_SEXT)
   846  			return 1;
   847  		break;
   848  	case C_LAUTO:
   849  		if(b == C_SAUTO)
   850  			return 1;
   851  		break;
   852  	case C_REG:
   853  		if(b == C_ZCON)
   854  			return r0iszero;
   855  		break;
   856  	case C_LOREG:
   857  		if(b == C_ZOREG || b == C_SOREG)
   858  			return 1;
   859  		break;
   860  	case C_SOREG:
   861  		if(b == C_ZOREG)
   862  			return 1;
   863  		break;
   864  
   865  	case C_ANY:
   866  		return 1;
   867  	}
   868  	return 0;
   869  }
   870  
   871  static int
   872  ocmp(const void *a1, const void *a2)
   873  {
   874  	const Optab *p1, *p2;
   875  	int n;
   876  
   877  	p1 = a1;
   878  	p2 = a2;
   879  	n = p1->as - p2->as;
   880  	if(n)
   881  		return n;
   882  	n = p1->a1 - p2->a1;
   883  	if(n)
   884  		return n;
   885  	n = p1->a2 - p2->a2;
   886  	if(n)
   887  		return n;
   888  	n = p1->a3 - p2->a3;
   889  	if(n)
   890  		return n;
   891  	n = p1->a4 - p2->a4;
   892  	if(n)
   893  		return n;
   894  	return 0;
   895  }
   896  
   897  static void
   898  buildop(Link *ctxt)
   899  {
   900  	int i, n, r;
   901  
   902  	for(i=0; i<C_NCLASS; i++)
   903  		for(n=0; n<C_NCLASS; n++)
   904  			xcmp[i][n] = cmp(n, i);
   905  	for(n=0; optab[n].as != AXXX; n++)
   906  		;
   907  	qsort(optab, n, sizeof(optab[0]), ocmp);
   908  	for(i=0; i<n; i++) {
   909  		r = optab[i].as;
   910  		oprange[r].start = optab+i;
   911  		while(optab[i].as == r)
   912  			i++;
   913  		oprange[r].stop = optab+i;
   914  		i--;
   915  		
   916  		switch(r)
   917  		{
   918  		default:
   919  			ctxt->diag("unknown op in build: %A", r);
   920  			sysfatal("bad code");
   921  		case ADCBF:	/* unary indexed: op (b+a); op (b) */
   922  			oprange[ADCBI] = oprange[r];
   923  			oprange[ADCBST] = oprange[r];
   924  			oprange[ADCBT] = oprange[r];
   925  			oprange[ADCBTST] = oprange[r];
   926  			oprange[ADCBZ] = oprange[r];
   927  			oprange[AICBI] = oprange[r];
   928  			break;
   929  		case AECOWX:	/* indexed store: op s,(b+a); op s,(b) */
   930  			oprange[ASTWCCC] = oprange[r];
   931  			oprange[ASTDCCC] = oprange[r];
   932  			break;
   933  		case AREM:	/* macro */
   934  			oprange[AREMCC] = oprange[r];
   935  			oprange[AREMV] = oprange[r];
   936  			oprange[AREMVCC] = oprange[r];
   937  			break;
   938  		case AREMU:
   939  			oprange[AREMU] = oprange[r];
   940  			oprange[AREMUCC] = oprange[r];
   941  			oprange[AREMUV] = oprange[r];
   942  			oprange[AREMUVCC] = oprange[r];
   943  			break;
   944  		case AREMD:
   945  			oprange[AREMDCC] = oprange[r];
   946  			oprange[AREMDV] = oprange[r];
   947  			oprange[AREMDVCC] = oprange[r];
   948  			break;
   949  		case AREMDU:
   950  			oprange[AREMDU] = oprange[r];
   951  			oprange[AREMDUCC] = oprange[r];
   952  			oprange[AREMDUV] = oprange[r];
   953  			oprange[AREMDUVCC] = oprange[r];
   954  			break;
   955  		case ADIVW:	/* op Rb[,Ra],Rd */
   956  			oprange[AMULHW] = oprange[r];
   957  			oprange[AMULHWCC] = oprange[r];
   958  			oprange[AMULHWU] = oprange[r];
   959  			oprange[AMULHWUCC] = oprange[r];
   960  			oprange[AMULLWCC] = oprange[r];
   961  			oprange[AMULLWVCC] = oprange[r];
   962  			oprange[AMULLWV] = oprange[r];
   963  			oprange[ADIVWCC] = oprange[r];
   964  			oprange[ADIVWV] = oprange[r];
   965  			oprange[ADIVWVCC] = oprange[r];
   966  			oprange[ADIVWU] = oprange[r];
   967  			oprange[ADIVWUCC] = oprange[r];
   968  			oprange[ADIVWUV] = oprange[r];
   969  			oprange[ADIVWUVCC] = oprange[r];
   970  			oprange[AADDCC] = oprange[r];
   971  			oprange[AADDCV] = oprange[r];
   972  			oprange[AADDCVCC] = oprange[r];
   973  			oprange[AADDV] = oprange[r];
   974  			oprange[AADDVCC] = oprange[r];
   975  			oprange[AADDE] = oprange[r];
   976  			oprange[AADDECC] = oprange[r];
   977  			oprange[AADDEV] = oprange[r];
   978  			oprange[AADDEVCC] = oprange[r];
   979  			oprange[ACRAND] = oprange[r];
   980  			oprange[ACRANDN] = oprange[r];
   981  			oprange[ACREQV] = oprange[r];
   982  			oprange[ACRNAND] = oprange[r];
   983  			oprange[ACRNOR] = oprange[r];
   984  			oprange[ACROR] = oprange[r];
   985  			oprange[ACRORN] = oprange[r];
   986  			oprange[ACRXOR] = oprange[r];
   987  			oprange[AMULHD] = oprange[r];
   988  			oprange[AMULHDCC] = oprange[r];
   989  			oprange[AMULHDU] = oprange[r];
   990  			oprange[AMULHDUCC] = oprange[r];
   991  			oprange[AMULLD] = oprange[r];
   992  			oprange[AMULLDCC] = oprange[r];
   993  			oprange[AMULLDVCC] = oprange[r];
   994  			oprange[AMULLDV] = oprange[r];
   995  			oprange[ADIVD] = oprange[r];
   996  			oprange[ADIVDCC] = oprange[r];
   997  			oprange[ADIVDVCC] = oprange[r];
   998  			oprange[ADIVDV] = oprange[r];
   999  			oprange[ADIVDU] = oprange[r];
  1000  			oprange[ADIVDUCC] = oprange[r];
  1001  			oprange[ADIVDUVCC] = oprange[r];
  1002  			oprange[ADIVDUCC] = oprange[r];
  1003  			break;
  1004  		case AMOVBZ:	/* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
  1005  			oprange[AMOVH] = oprange[r];
  1006  			oprange[AMOVHZ] = oprange[r];
  1007  			break;
  1008  		case AMOVBZU:	/* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
  1009  			oprange[AMOVHU] = oprange[r];
  1010  			oprange[AMOVHZU] = oprange[r];
  1011  			oprange[AMOVWU] = oprange[r];
  1012  			oprange[AMOVWZU] = oprange[r];
  1013  			oprange[AMOVDU] = oprange[r];
  1014  			oprange[AMOVMW] = oprange[r];
  1015  			break;
  1016  		case AAND:	/* logical op Rb,Rs,Ra; no literal */
  1017  			oprange[AANDN] = oprange[r];
  1018  			oprange[AANDNCC] = oprange[r];
  1019  			oprange[AEQV] = oprange[r];
  1020  			oprange[AEQVCC] = oprange[r];
  1021  			oprange[ANAND] = oprange[r];
  1022  			oprange[ANANDCC] = oprange[r];
  1023  			oprange[ANOR] = oprange[r];
  1024  			oprange[ANORCC] = oprange[r];
  1025  			oprange[AORCC] = oprange[r];
  1026  			oprange[AORN] = oprange[r];
  1027  			oprange[AORNCC] = oprange[r];
  1028  			oprange[AXORCC] = oprange[r];
  1029  			break;
  1030  		case AADDME:	/* op Ra, Rd */
  1031  			oprange[AADDMECC] = oprange[r];
  1032  			oprange[AADDMEV] = oprange[r];
  1033  			oprange[AADDMEVCC] = oprange[r];
  1034  			oprange[AADDZE] = oprange[r];
  1035  			oprange[AADDZECC] = oprange[r];
  1036  			oprange[AADDZEV] = oprange[r];
  1037  			oprange[AADDZEVCC] = oprange[r];
  1038  			oprange[ASUBME] = oprange[r];
  1039  			oprange[ASUBMECC] = oprange[r];
  1040  			oprange[ASUBMEV] = oprange[r];
  1041  			oprange[ASUBMEVCC] = oprange[r];
  1042  			oprange[ASUBZE] = oprange[r];
  1043  			oprange[ASUBZECC] = oprange[r];
  1044  			oprange[ASUBZEV] = oprange[r];
  1045  			oprange[ASUBZEVCC] = oprange[r];
  1046  			break;
  1047  		case AADDC:
  1048  			oprange[AADDCCC] = oprange[r];
  1049  			break;
  1050  		case ABEQ:
  1051  			oprange[ABGE] = oprange[r];
  1052  			oprange[ABGT] = oprange[r];
  1053  			oprange[ABLE] = oprange[r];
  1054  			oprange[ABLT] = oprange[r];
  1055  			oprange[ABNE] = oprange[r];
  1056  			oprange[ABVC] = oprange[r];
  1057  			oprange[ABVS] = oprange[r];
  1058  			break;
  1059  		case ABR:
  1060  			oprange[ABL] = oprange[r];
  1061  			break;
  1062  		case ABC:
  1063  			oprange[ABCL] = oprange[r];
  1064  			break;
  1065  		case AEXTSB:	/* op Rs, Ra */
  1066  			oprange[AEXTSBCC] = oprange[r];
  1067  			oprange[AEXTSH] = oprange[r];
  1068  			oprange[AEXTSHCC] = oprange[r];
  1069  			oprange[ACNTLZW] = oprange[r];
  1070  			oprange[ACNTLZWCC] = oprange[r];
  1071  			oprange[ACNTLZD] = oprange[r];
  1072  			oprange[AEXTSW] = oprange[r];
  1073  			oprange[AEXTSWCC] = oprange[r];
  1074  			oprange[ACNTLZDCC] = oprange[r];
  1075  			break;
  1076  		case AFABS:	/* fop [s,]d */
  1077  			oprange[AFABSCC] = oprange[r];
  1078  			oprange[AFNABS] = oprange[r];
  1079  			oprange[AFNABSCC] = oprange[r];
  1080  			oprange[AFNEG] = oprange[r];
  1081  			oprange[AFNEGCC] = oprange[r];
  1082  			oprange[AFRSP] = oprange[r];
  1083  			oprange[AFRSPCC] = oprange[r];
  1084  			oprange[AFCTIW] = oprange[r];
  1085  			oprange[AFCTIWCC] = oprange[r];
  1086  			oprange[AFCTIWZ] = oprange[r];
  1087  			oprange[AFCTIWZCC] = oprange[r];
  1088  			oprange[AFCTID] = oprange[r];
  1089  			oprange[AFCTIDCC] = oprange[r];
  1090  			oprange[AFCTIDZ] = oprange[r];
  1091  			oprange[AFCTIDZCC] = oprange[r];
  1092  			oprange[AFCFID] = oprange[r];
  1093  			oprange[AFCFIDCC] = oprange[r];
  1094  			oprange[AFRES] = oprange[r];
  1095  			oprange[AFRESCC] = oprange[r];
  1096  			oprange[AFRSQRTE] = oprange[r];
  1097  			oprange[AFRSQRTECC] = oprange[r];
  1098  			oprange[AFSQRT] = oprange[r];
  1099  			oprange[AFSQRTCC] = oprange[r];
  1100  			oprange[AFSQRTS] = oprange[r];
  1101  			oprange[AFSQRTSCC] = oprange[r];
  1102  			break;
  1103  		case AFADD:
  1104  			oprange[AFADDS] = oprange[r];
  1105  			oprange[AFADDCC] = oprange[r];
  1106  			oprange[AFADDSCC] = oprange[r];
  1107  			oprange[AFDIV] = oprange[r];
  1108  			oprange[AFDIVS] = oprange[r];
  1109  			oprange[AFDIVCC] = oprange[r];
  1110  			oprange[AFDIVSCC] = oprange[r];
  1111  			oprange[AFSUB] = oprange[r];
  1112  			oprange[AFSUBS] = oprange[r];
  1113  			oprange[AFSUBCC] = oprange[r];
  1114  			oprange[AFSUBSCC] = oprange[r];
  1115  			break;
  1116  		case AFMADD:
  1117  			oprange[AFMADDCC] = oprange[r];
  1118  			oprange[AFMADDS] = oprange[r];
  1119  			oprange[AFMADDSCC] = oprange[r];
  1120  			oprange[AFMSUB] = oprange[r];
  1121  			oprange[AFMSUBCC] = oprange[r];
  1122  			oprange[AFMSUBS] = oprange[r];
  1123  			oprange[AFMSUBSCC] = oprange[r];
  1124  			oprange[AFNMADD] = oprange[r];
  1125  			oprange[AFNMADDCC] = oprange[r];
  1126  			oprange[AFNMADDS] = oprange[r];
  1127  			oprange[AFNMADDSCC] = oprange[r];
  1128  			oprange[AFNMSUB] = oprange[r];
  1129  			oprange[AFNMSUBCC] = oprange[r];
  1130  			oprange[AFNMSUBS] = oprange[r];
  1131  			oprange[AFNMSUBSCC] = oprange[r];
  1132  			oprange[AFSEL] = oprange[r];
  1133  			oprange[AFSELCC] = oprange[r];
  1134  			break;
  1135  		case AFMUL:
  1136  			oprange[AFMULS] = oprange[r];
  1137  			oprange[AFMULCC] = oprange[r];
  1138  			oprange[AFMULSCC] = oprange[r];
  1139  			break;
  1140  		case AFCMPO:
  1141  			oprange[AFCMPU] = oprange[r];
  1142  			break;
  1143  		case AMTFSB0:
  1144  			oprange[AMTFSB0CC] = oprange[r];
  1145  			oprange[AMTFSB1] = oprange[r];
  1146  			oprange[AMTFSB1CC] = oprange[r];
  1147  			break;
  1148  		case ANEG:	/* op [Ra,] Rd */
  1149  			oprange[ANEGCC] = oprange[r];
  1150  			oprange[ANEGV] = oprange[r];
  1151  			oprange[ANEGVCC] = oprange[r];
  1152  			break;
  1153  		case AOR:	/* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
  1154  			oprange[AXOR] = oprange[r];
  1155  			break;
  1156  		case ASLW:
  1157  			oprange[ASLWCC] = oprange[r];
  1158  			oprange[ASRW] = oprange[r];
  1159  			oprange[ASRWCC] = oprange[r];
  1160  			break;
  1161  		case ASLD:
  1162  			oprange[ASLDCC] = oprange[r];
  1163  			oprange[ASRD] = oprange[r];
  1164  			oprange[ASRDCC] = oprange[r];
  1165  			break;
  1166  		case ASRAW:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
  1167  			oprange[ASRAWCC] = oprange[r];
  1168  			break;
  1169  		case ASRAD:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
  1170  			oprange[ASRADCC] = oprange[r];
  1171  			break;
  1172  		case ASUB:	/* SUB Ra,Rb,Rd => subf Rd,ra,rb */
  1173  			oprange[ASUB] = oprange[r];
  1174  			oprange[ASUBCC] = oprange[r];
  1175  			oprange[ASUBV] = oprange[r];
  1176  			oprange[ASUBVCC] = oprange[r];
  1177  			oprange[ASUBCCC] = oprange[r];
  1178  			oprange[ASUBCV] = oprange[r];
  1179  			oprange[ASUBCVCC] = oprange[r];
  1180  			oprange[ASUBE] = oprange[r];
  1181  			oprange[ASUBECC] = oprange[r];
  1182  			oprange[ASUBEV] = oprange[r];
  1183  			oprange[ASUBEVCC] = oprange[r];
  1184  			break;
  1185  		case ASYNC:
  1186  			oprange[AISYNC] = oprange[r];
  1187  			oprange[APTESYNC] = oprange[r];
  1188  			oprange[ATLBSYNC] = oprange[r];
  1189  			break;
  1190  		case ARLWMI:
  1191  			oprange[ARLWMICC] = oprange[r];
  1192  			oprange[ARLWNM] = oprange[r];
  1193  			oprange[ARLWNMCC] = oprange[r];
  1194  			break;
  1195  		case ARLDMI:
  1196  			oprange[ARLDMICC] = oprange[r];
  1197  			break;
  1198  		case ARLDC:
  1199  			oprange[ARLDCCC] = oprange[r];
  1200  			break;
  1201  		case ARLDCL:
  1202  			oprange[ARLDCR] = oprange[r];
  1203  			oprange[ARLDCLCC] = oprange[r];
  1204  			oprange[ARLDCRCC] = oprange[r];
  1205  			break;
  1206  		case AFMOVD:
  1207  			oprange[AFMOVDCC] = oprange[r];
  1208  			oprange[AFMOVDU] = oprange[r];
  1209  			oprange[AFMOVS] = oprange[r];
  1210  			oprange[AFMOVSU] = oprange[r];
  1211  			break;
  1212  		case AECIWX:
  1213  			oprange[ALWAR] = oprange[r];
  1214  			oprange[ALDAR] = oprange[r];
  1215  			break;
  1216  		case ASYSCALL:	/* just the op; flow of control */
  1217  			oprange[ARFI] = oprange[r];
  1218  			oprange[ARFCI] = oprange[r];
  1219  			oprange[ARFID] = oprange[r];
  1220  			oprange[AHRFID] = oprange[r];
  1221  			break;
  1222  		case AMOVHBR:
  1223  			oprange[AMOVWBR] = oprange[r];
  1224  			break;
  1225  		case ASLBMFEE:
  1226  			oprange[ASLBMFEV] = oprange[r];
  1227  			break;
  1228  		case ATW:
  1229  			oprange[ATD] = oprange[r];
  1230  			break;
  1231  		case ATLBIE:
  1232  			oprange[ASLBIE] = oprange[r];
  1233  			oprange[ATLBIEL] = oprange[r];
  1234  			break;
  1235  		case AEIEIO:
  1236  			oprange[ASLBIA] = oprange[r];
  1237  			break;
  1238  		case ACMP:
  1239  			oprange[ACMPW] = oprange[r];
  1240  			break;
  1241  		case ACMPU:
  1242  			oprange[ACMPWU] = oprange[r];
  1243  			break;
  1244  		case AADD:
  1245  		case AANDCC:	/* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
  1246  		case ALSW:
  1247  		case AMOVW:	/* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
  1248  		case AMOVWZ:	/* load/store/move word with zero extension; move 32-bit literals  */
  1249  		case AMOVD:	/* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
  1250  		case AMOVB:	/* macro: move byte with sign extension */
  1251  		case AMOVBU:	/* macro: move byte with sign extension & update */
  1252  		case AMOVFL:
  1253  		case AMULLW:	/* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
  1254  		case ASUBC:	/* op r1,$s,r3; op r1[,r2],r3 */
  1255  		case ASTSW:
  1256  		case ASLBMTE:
  1257  		case AWORD:
  1258  		case ADWORD:
  1259  		case ANOP:
  1260  		case ATEXT:
  1261  		case AUNDEF:
  1262  		case AUSEFIELD:
  1263  		case AFUNCDATA:
  1264  		case APCDATA:
  1265  		case ADUFFZERO:
  1266  		case ADUFFCOPY:
  1267  			break;
  1268  		}
  1269  	}
  1270  }
  1271  
  1272  #define	OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
  1273  #define	OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
  1274  #define	OP(o,xo) OPVCC((o),(xo),0,0)
  1275  
  1276  /* the order is dest, a/s, b/imm for both arithmetic and logical operations */
  1277  #define	AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  1278  #define	AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
  1279  #define	LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  1280  #define	LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
  1281  #define	OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
  1282  #define	OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
  1283  #define	OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
  1284  #define	OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
  1285  					(((mb)&31L)<<6)|(((me)&31L)<<1))
  1286  
  1287  #define	OP_ADD	OPVCC(31,266,0,0)
  1288  #define	OP_ADDI	OPVCC(14,0,0,0)
  1289  #define	OP_ADDIS OPVCC(15,0,0,0)
  1290  #define	OP_ANDI	OPVCC(28,0,0,0)
  1291  #define	OP_EXTSB	OPVCC(31,954,0,0)
  1292  #define	OP_EXTSH OPVCC(31,922,0,0)
  1293  #define	OP_EXTSW OPVCC(31,986,0,0)
  1294  #define	OP_MCRF	OPVCC(19,0,0,0)
  1295  #define	OP_MCRFS OPVCC(63,64,0,0)
  1296  #define	OP_MCRXR OPVCC(31,512,0,0)
  1297  #define	OP_MFCR	OPVCC(31,19,0,0)
  1298  #define	OP_MFFS	OPVCC(63,583,0,0)
  1299  #define	OP_MFMSR OPVCC(31,83,0,0)
  1300  #define	OP_MFSPR OPVCC(31,339,0,0)
  1301  #define	OP_MFSR	OPVCC(31,595,0,0)
  1302  #define	OP_MFSRIN	OPVCC(31,659,0,0)
  1303  #define	OP_MTCRF OPVCC(31,144,0,0)
  1304  #define	OP_MTFSF OPVCC(63,711,0,0)
  1305  #define	OP_MTFSFI OPVCC(63,134,0,0)
  1306  #define	OP_MTMSR OPVCC(31,146,0,0)
  1307  #define	OP_MTMSRD OPVCC(31,178,0,0)
  1308  #define	OP_MTSPR OPVCC(31,467,0,0)
  1309  #define	OP_MTSR	OPVCC(31,210,0,0)
  1310  #define	OP_MTSRIN	OPVCC(31,242,0,0)
  1311  #define	OP_MULLW OPVCC(31,235,0,0)
  1312  #define	OP_MULLD OPVCC(31,233,0,0)
  1313  #define	OP_OR	OPVCC(31,444,0,0)
  1314  #define	OP_ORI	OPVCC(24,0,0,0)
  1315  #define	OP_ORIS	OPVCC(25,0,0,0)
  1316  #define	OP_RLWINM	OPVCC(21,0,0,0)
  1317  #define	OP_SUBF	OPVCC(31,40,0,0)
  1318  #define	OP_RLDIC	OPVCC(30,4,0,0)
  1319  #define	OP_RLDICR	OPVCC(30,2,0,0)
  1320  #define	OP_RLDICL	OPVCC(30,0,0,0)
  1321  
  1322  #define	oclass(v)	((v).class-1)
  1323  
  1324  // add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
  1325  static void
  1326  addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2)
  1327  {
  1328  	Reloc *rel;
  1329  
  1330  	rel = addrel(ctxt->cursym);
  1331  	rel->off = ctxt->pc;
  1332  	rel->siz = 8;
  1333  	rel->sym = s;
  1334  	rel->add = ((uvlong)*o1<<32) | (uint32)*o2;
  1335  	rel->type = R_ADDRPOWER;
  1336  }
  1337  
  1338  /*
  1339   * 32-bit masks
  1340   */
  1341  static int
  1342  getmask(uchar *m, uint32 v)
  1343  {
  1344  	int i;
  1345  
  1346  	m[0] = m[1] = 0;
  1347  	if(v != ~0U && v & (1<<31) && v & 1){	/* MB > ME */
  1348  		if(getmask(m, ~v)){
  1349  			i = m[0]; m[0] = m[1]+1; m[1] = i-1;
  1350  			return 1;
  1351  		}
  1352  		return 0;
  1353  	}
  1354  	for(i=0; i<32; i++)
  1355  		if(v & (1<<(31-i))){
  1356  			m[0] = i;
  1357  			do {
  1358  				m[1] = i;
  1359  			} while(++i<32 && (v & (1<<(31-i))) != 0);
  1360  			for(; i<32; i++)
  1361  				if(v & (1<<(31-i)))
  1362  					return 0;
  1363  			return 1;
  1364  		}
  1365  	return 0;
  1366  }
  1367  
  1368  static void
  1369  maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v)
  1370  {
  1371  	if(!getmask(m, v))
  1372  		ctxt->diag("cannot generate mask #%lux\n%P", v, p);
  1373  }
  1374  
  1375  /*
  1376   * 64-bit masks (rldic etc)
  1377   */
  1378  static int
  1379  getmask64(uchar *m, uvlong v)
  1380  {
  1381  	int i;
  1382  
  1383  	m[0] = m[1] = 0;
  1384  	for(i=0; i<64; i++)
  1385  		if(v & ((uvlong)1<<(63-i))){
  1386  			m[0] = i;
  1387  			do {
  1388  				m[1] = i;
  1389  			} while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0);
  1390  			for(; i<64; i++)
  1391  				if(v & ((uvlong)1<<(63-i)))
  1392  					return 0;
  1393  			return 1;
  1394  		}
  1395  	return 0;
  1396  }
  1397  
  1398  static void
  1399  maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v)
  1400  {
  1401  	if(!getmask64(m, v))
  1402  		ctxt->diag("cannot generate mask #%llux\n%P", v, p);
  1403  }
  1404  
  1405  static uint32
  1406  loadu32(int r, vlong d)
  1407  {
  1408  	int32 v;
  1409  
  1410  	v = d>>16;
  1411  	if(isuint32(d))
  1412  		return LOP_IRR(OP_ORIS, r, REGZERO, v);
  1413  	return AOP_IRR(OP_ADDIS, r, REGZERO, v);
  1414  }
  1415  
  1416  static uint16
  1417  high16adjusted(int32 d)
  1418  {
  1419  	if(d & 0x8000)
  1420  		return (d>>16) + 1;
  1421  	return d>>16;
  1422  }
  1423  
  1424  static void
  1425  asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
  1426  {
  1427  	int32 o1, o2, o3, o4, o5, v, t;
  1428  	vlong d;
  1429  	int r, a;
  1430  	uchar mask[2];
  1431  	Reloc *rel;
  1432  
  1433  	o1 = 0;
  1434  	o2 = 0;
  1435  	o3 = 0;
  1436  	o4 = 0;
  1437  	o5 = 0;
  1438  
  1439  //print("%P => case %d\n", p, o->type);
  1440  	switch(o->type) {
  1441  	default:
  1442  		ctxt->diag("unknown type %d", o->type);
  1443  		prasm(p);
  1444  		break;
  1445  
  1446  	case 0:		/* pseudo ops */
  1447  		break;
  1448  
  1449  	case 1:		/* mov r1,r2 ==> OR Rs,Rs,Ra */
  1450  		if(p->to.reg == REGZERO && p->from.type == D_CONST) {
  1451  			v = regoff(ctxt, &p->from);
  1452  			if(r0iszero && v != 0) {
  1453  				//nerrors--;
  1454  				ctxt->diag("literal operation on R0\n%P", p);
  1455  			}
  1456  			o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
  1457  			break;
  1458  		}
  1459  		o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
  1460  		break;
  1461  
  1462  	case 2:		/* int/cr/fp op Rb,[Ra],Rd */
  1463  		r = p->reg;
  1464  		if(r == NREG)
  1465  			r = p->to.reg;
  1466  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1467  		break;
  1468  
  1469  	case 3:		/* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
  1470  		d = vregoff(ctxt, &p->from);
  1471  		v = d;
  1472  		r = p->from.reg;
  1473  		if(r == NREG)
  1474  			r = o->param;
  1475  		if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
  1476  			ctxt->diag("literal operation on R0\n%P", p);
  1477  		a = OP_ADDI;
  1478  		if(o->a1 == C_UCON) {
  1479  			if((d&0xffff) != 0)
  1480  				sysfatal("invalid handling of %P", p);
  1481  			v >>= 16;
  1482  			if(r == REGZERO && isuint32(d)){
  1483  				o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v);
  1484  				break;
  1485  			}
  1486  			a = OP_ADDIS;
  1487  		} else {
  1488  			if((int16)d != d)
  1489  				sysfatal("invalid handling of %P", p);
  1490  		}
  1491  		o1 = AOP_IRR(a, p->to.reg, r, v);
  1492  		break;
  1493  
  1494  	case 4:		/* add/mul $scon,[r1],r2 */
  1495  		v = regoff(ctxt, &p->from);
  1496  		r = p->reg;
  1497  		if(r == NREG)
  1498  			r = p->to.reg;
  1499  		if(r0iszero && p->to.reg == 0)
  1500  			ctxt->diag("literal operation on R0\n%P", p);
  1501  		if((int16)v != v)
  1502  			sysfatal("mishandled instruction %P", p);
  1503  		o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
  1504  		break;
  1505  
  1506  	case 5:		/* syscall */
  1507  		o1 = oprrr(ctxt, p->as);
  1508  		break;
  1509  
  1510  	case 6:		/* logical op Rb,[Rs,]Ra; no literal */
  1511  		r = p->reg;
  1512  		if(r == NREG)
  1513  			r = p->to.reg;
  1514  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1515  		break;
  1516  
  1517  	case 7:		/* mov r, soreg ==> stw o(r) */
  1518  		r = p->to.reg;
  1519  		if(r == NREG)
  1520  			r = o->param;
  1521  		v = regoff(ctxt, &p->to);
  1522  		if(p->to.type == D_OREG && p->reg != NREG) {
  1523  			if(v)
  1524  				ctxt->diag("illegal indexed instruction\n%P", p);
  1525  			o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r);
  1526  		} else {
  1527  			if((int16)v != v)
  1528  				sysfatal("mishandled instruction %P", p);	
  1529  			o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v);
  1530  		}
  1531  		break;
  1532  
  1533  	case 8:		/* mov soreg, r ==> lbz/lhz/lwz o(r) */
  1534  		r = p->from.reg;
  1535  		if(r == NREG)
  1536  			r = o->param;
  1537  		v = regoff(ctxt, &p->from);
  1538  		if(p->from.type == D_OREG && p->reg != NREG) {
  1539  			if(v)
  1540  				ctxt->diag("illegal indexed instruction\n%P", p);
  1541  			o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
  1542  		} else {
  1543  			if((int16)v != v)
  1544  				sysfatal("mishandled instruction %P", p);
  1545  			o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
  1546  		}
  1547  		break;
  1548  
  1549  	case 9:		/* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
  1550  		r = p->from.reg;
  1551  		if(r == NREG)
  1552  			r = o->param;
  1553  		v = regoff(ctxt, &p->from);
  1554  		if(p->from.type == D_OREG && p->reg != NREG) {
  1555  			if(v)
  1556  				ctxt->diag("illegal indexed instruction\n%P", p);
  1557  			o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
  1558  		} else
  1559  			o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
  1560  		o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  1561  		break;
  1562  
  1563  	case 10:		/* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
  1564  		r = p->reg;
  1565  		if(r == NREG)
  1566  			r = p->to.reg;
  1567  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r);
  1568  		break;
  1569  
  1570  	case 11:	/* br/bl lbra */
  1571  		v = 0;
  1572  		if(p->pcond) {
  1573  			v = p->pcond->pc - p->pc;
  1574  			if(v & 03) {
  1575  				ctxt->diag("odd branch target address\n%P", p);
  1576  				v &= ~03;
  1577  			}
  1578  			if(v < -(1L<<25) || v >= (1L<<24))
  1579  				ctxt->diag("branch too far\n%P", p);
  1580  		}
  1581  		o1 = OP_BR(opirr(ctxt, p->as), v, 0);
  1582  		if(p->to.sym != nil) {
  1583  			rel = addrel(ctxt->cursym);
  1584  			rel->off = ctxt->pc;
  1585  			rel->siz = 4;
  1586  			rel->sym = p->to.sym;
  1587  			v += p->to.offset;
  1588  			if(v & 03) {
  1589  				ctxt->diag("odd branch target address\n%P", p);
  1590  				v &= ~03;
  1591  			}
  1592  			rel->add = v;
  1593  			rel->type = R_CALLPOWER;
  1594  		}
  1595  		break;
  1596  
  1597  	case 12:	/* movb r,r (extsb); movw r,r (extsw) */
  1598  		if(p->to.reg == REGZERO && p->from.type == D_CONST) {
  1599  			v = regoff(ctxt, &p->from);
  1600  			if(r0iszero && v != 0) {
  1601  				ctxt->diag("literal operation on R0\n%P", p);
  1602  			}
  1603  			o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
  1604  			break;
  1605  		}
  1606  		if(p->as == AMOVW)
  1607  			o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0);
  1608  		else
  1609  			o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
  1610  		break;
  1611  
  1612  	case 13:	/* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
  1613  		if(p->as == AMOVBZ)
  1614  			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
  1615  		else if(p->as == AMOVH)
  1616  			o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
  1617  		else if(p->as == AMOVHZ)
  1618  			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
  1619  		else if(p->as == AMOVWZ)
  1620  			o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5);	/* MB=32 */
  1621  		else
  1622  			ctxt->diag("internal: bad mov[bhw]z\n%P", p);
  1623  		break;
  1624  
  1625  	case 14:	/* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
  1626  		r = p->reg;
  1627  		if(r == NREG)
  1628  			r = p->to.reg;
  1629  		d = vregoff(ctxt, &p->from3);
  1630  		maskgen64(ctxt, p, mask, d);
  1631  		switch(p->as){
  1632  		case ARLDCL: case ARLDCLCC:
  1633  			a = mask[0];	/* MB */
  1634  			if(mask[1] != 63)
  1635  				ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p);
  1636  			break;
  1637  		case ARLDCR: case ARLDCRCC:
  1638  			a = mask[1];	/* ME */
  1639  			if(mask[0] != 0)
  1640  				ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p);
  1641  			break;
  1642  		default:
  1643  			ctxt->diag("unexpected op in rldc case\n%P", p);
  1644  			a = 0;
  1645  		}
  1646  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1647  		o1 |= (a&31L)<<6;
  1648  		if(a & 0x20)
  1649  			o1 |= 1<<5;	/* mb[5] is top bit */
  1650  		break;
  1651  
  1652  	case 17:	/* bc bo,bi,lbra (same for now) */
  1653  	case 16:	/* bc bo,bi,sbra */
  1654  		a = 0;
  1655  		if(p->from.type == D_CONST)
  1656  			a = regoff(ctxt, &p->from);
  1657  		r = p->reg;
  1658  		if(r == NREG)
  1659  			r = 0;
  1660  		v = 0;
  1661  		if(p->pcond)
  1662  			v = p->pcond->pc - p->pc;
  1663  		if(v & 03) {
  1664  			ctxt->diag("odd branch target address\n%P", p);
  1665  			v &= ~03;
  1666  		}
  1667  		if(v < -(1L<<16) || v >= (1L<<15))
  1668  			ctxt->diag("branch too far\n%P", p);
  1669  		o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0);
  1670  		break;
  1671  
  1672  	case 15:	/* br/bl (r) => mov r,lr; br/bl (lr) */
  1673  		if(p->as == ABC || p->as == ABCL)
  1674  			v = regoff(ctxt, &p->to)&31L;
  1675  		else
  1676  			v = 20;	/* unconditional */
  1677  		r = p->reg;
  1678  		if(r == NREG)
  1679  			r = 0;
  1680  		o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
  1681  		o2 = OPVCC(19, 16, 0, 0);
  1682  		if(p->as == ABL || p->as == ABCL)
  1683  			o2 |= 1;
  1684  		o2 = OP_BCR(o2, v, r);
  1685  		break;
  1686  
  1687  	case 18:	/* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
  1688  		if(p->as == ABC || p->as == ABCL)
  1689  			v = regoff(ctxt, &p->from)&31L;
  1690  		else
  1691  			v = 20;	/* unconditional */
  1692  		r = p->reg;
  1693  		if(r == NREG)
  1694  			r = 0;
  1695  		switch(oclass(p->to)) {
  1696  		case C_CTR:
  1697  			o1 = OPVCC(19, 528, 0, 0);
  1698  			break;
  1699  		case C_LR:
  1700  			o1 = OPVCC(19, 16, 0, 0);
  1701  			break;
  1702  		default:
  1703  			ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p);
  1704  			v = 0;
  1705  		}
  1706  		if(p->as == ABL || p->as == ABCL)
  1707  			o1 |= 1;
  1708  		o1 = OP_BCR(o1, v, r);
  1709  		break;
  1710  
  1711  	case 19:	/* mov $lcon,r ==> cau+or */
  1712  		d = vregoff(ctxt, &p->from);
  1713  		if(p->from.sym == nil) {
  1714  			o1 = loadu32(p->to.reg, d);
  1715  			o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d);
  1716  		} else {
  1717  			o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d));
  1718  			o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d);
  1719  			addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  1720  		}
  1721  		//if(dlm) reloc(&p->from, p->pc, 0);
  1722  		break;
  1723  
  1724  	case 20:	/* add $ucon,,r */
  1725  		v = regoff(ctxt, &p->from);
  1726  		r = p->reg;
  1727  		if(r == NREG)
  1728  			r = p->to.reg;
  1729  		if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
  1730  			ctxt->diag("literal operation on R0\n%P", p);
  1731  		o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);
  1732  		break;
  1733  
  1734  	case 22:	/* add $lcon,r1,r2 ==> cau+or+add */	/* could do add/sub more efficiently */
  1735  		if(p->to.reg == REGTMP || p->reg == REGTMP)
  1736  			ctxt->diag("cant synthesize large constant\n%P", p);
  1737  		d = vregoff(ctxt, &p->from);
  1738  		o1 = loadu32(REGTMP, d);
  1739  		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
  1740  		r = p->reg;
  1741  		if(r == NREG)
  1742  			r = p->to.reg;
  1743  		o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
  1744  		if(p->from.sym != nil)
  1745  			ctxt->diag("%P is not supported", p);
  1746  		//if(dlm) reloc(&p->from, p->pc, 0);
  1747  		break;
  1748  
  1749  	case 23:	/* and $lcon,r1,r2 ==> cau+or+and */	/* masks could be done using rlnm etc. */
  1750  		if(p->to.reg == REGTMP || p->reg == REGTMP)
  1751  			ctxt->diag("cant synthesize large constant\n%P", p);
  1752  		d = vregoff(ctxt, &p->from);
  1753  		o1 = loadu32(REGTMP, d);
  1754  		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
  1755  		r = p->reg;
  1756  		if(r == NREG)
  1757  			r = p->to.reg;
  1758  		o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
  1759  		if(p->from.sym != nil)
  1760  			ctxt->diag("%P is not supported", p);
  1761  		//if(dlm) reloc(&p->from, p->pc, 0);
  1762  		break;
  1763  /*24*/
  1764  
  1765  	case 25:	/* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
  1766  		v = regoff(ctxt, &p->from);
  1767  		if(v < 0)
  1768  			v = 0;
  1769  		else if(v > 63)
  1770  			v = 63;
  1771  		r = p->reg;
  1772  		if(r == NREG)
  1773  			r = p->to.reg;
  1774  		switch(p->as){
  1775  		case ASLD: case ASLDCC:
  1776  			a = 63-v;
  1777  			o1 = OP_RLDICR;
  1778  			break;
  1779  		case ASRD: case ASRDCC:
  1780  			a = v;
  1781  			v = 64-v;
  1782  			o1 = OP_RLDICL;
  1783  			break;
  1784  		default:
  1785  			ctxt->diag("unexpected op in sldi case\n%P", p);
  1786  			a = 0;
  1787  			o1 = 0;
  1788  		}
  1789  		o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F));
  1790  		o1 |= (a&31L)<<6;
  1791  		if(v & 0x20)
  1792  			o1 |= 1<<1;
  1793  		if(a & 0x20)
  1794  			o1 |= 1<<5;	/* mb[5] is top bit */
  1795  		if(p->as == ASLDCC || p->as == ASRDCC)
  1796  			o1 |= 1;	/* Rc */
  1797  		break;
  1798  
  1799  	case 26:	/* mov $lsext/auto/oreg,,r2 ==> addis+addi */
  1800  		if(p->to.reg == REGTMP)
  1801  			ctxt->diag("can't synthesize large constant\n%P", p);
  1802  		v = regoff(ctxt, &p->from);
  1803  		if(v & 0x8000L)
  1804  			v += 0x10000L;
  1805  		r = p->from.reg;
  1806  		if(r == NREG)
  1807  			r = o->param;
  1808  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  1809  		o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
  1810  		break;
  1811  
  1812  	case 27:		/* subc ra,$simm,rd => subfic rd,ra,$simm */
  1813  		v = regoff(ctxt, &p->from3);
  1814  		r = p->from.reg;
  1815  		o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
  1816  		break;
  1817  
  1818  	case 28:	/* subc r1,$lcon,r2 ==> cau+or+subfc */
  1819  		if(p->to.reg == REGTMP || p->from.reg == REGTMP)
  1820  			ctxt->diag("can't synthesize large constant\n%P", p);
  1821  		v = regoff(ctxt, &p->from3);
  1822  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
  1823  		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
  1824  		o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, REGTMP);
  1825  		if(p->from.sym != nil)
  1826  			ctxt->diag("%P is not supported", p);
  1827  		//if(dlm) reloc(&p->from3, p->pc, 0);
  1828  		break;
  1829  
  1830  	case 29:	/* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
  1831  		v = regoff(ctxt, &p->from);
  1832  		d = vregoff(ctxt, &p->from3);
  1833  		maskgen64(ctxt, p, mask, d);
  1834  		switch(p->as){
  1835  		case ARLDC: case ARLDCCC:
  1836  			a = mask[0];	/* MB */
  1837  			if(mask[1] != (63-v))
  1838  				ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
  1839  			break;
  1840  		case ARLDCL: case ARLDCLCC:
  1841  			a = mask[0];	/* MB */
  1842  			if(mask[1] != 63)
  1843  				ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
  1844  			break;
  1845  		case ARLDCR: case ARLDCRCC:
  1846  			a = mask[1];	/* ME */
  1847  			if(mask[0] != 0)
  1848  				ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
  1849  			break;
  1850  		default:
  1851  			ctxt->diag("unexpected op in rldic case\n%P", p);
  1852  			a = 0;
  1853  		}
  1854  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
  1855  		o1 |= (a&31L)<<6;
  1856  		if(v & 0x20)
  1857  			o1 |= 1<<1;
  1858  		if(a & 0x20)
  1859  			o1 |= 1<<5;	/* mb[5] is top bit */
  1860  		break;
  1861  
  1862  	case 30:	/* rldimi $sh,s,$mask,a */
  1863  		v = regoff(ctxt, &p->from);
  1864  		d = vregoff(ctxt, &p->from3);
  1865  		maskgen64(ctxt, p, mask, d);
  1866  		if(mask[1] != (63-v))
  1867  			ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
  1868  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
  1869  		o1 |= (mask[0]&31L)<<6;
  1870  		if(v & 0x20)
  1871  			o1 |= 1<<1;
  1872  		if(mask[0] & 0x20)
  1873  			o1 |= 1<<5;	/* mb[5] is top bit */
  1874  		break;
  1875  
  1876  	case 31:	/* dword */
  1877  		d = vregoff(ctxt, &p->from);
  1878  		if(ctxt->arch->endian == BigEndian) {
  1879  			o1 = d>>32;
  1880  			o2 = d;
  1881  		} else {
  1882  			o1 = d;
  1883  			o2 = d>>32;
  1884  		}
  1885  		if(p->from.sym != nil) {
  1886  			rel = addrel(ctxt->cursym);
  1887  			rel->off = ctxt->pc;
  1888  			rel->siz = 8;
  1889  			rel->sym = p->from.sym;
  1890  			rel->add = p->from.offset;
  1891  			rel->type = R_ADDR;
  1892  			o1 = o2 = 0;
  1893  		}
  1894  		break;
  1895  
  1896  	case 32:	/* fmul frc,fra,frd */
  1897  		r = p->reg;
  1898  		if(r == NREG)
  1899  			r = p->to.reg;
  1900  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
  1901  		break;
  1902  
  1903  	case 33:	/* fabs [frb,]frd; fmr. frb,frd */
  1904  		r = p->from.reg;
  1905  		if(oclass(p->from) == C_NONE)
  1906  			r = p->to.reg;
  1907  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, r);
  1908  		break;
  1909  
  1910  	case 34:	/* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
  1911  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
  1912  		break;
  1913  
  1914  	case 35:	/* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
  1915  		v = regoff(ctxt, &p->to);
  1916  		if(v & 0x8000L)
  1917  			v += 0x10000L;
  1918  		r = p->to.reg;
  1919  		if(r == NREG)
  1920  			r = o->param;
  1921  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  1922  		o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
  1923  		break;
  1924  
  1925  	case 36:	/* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
  1926  		v = regoff(ctxt, &p->from);
  1927  		if(v & 0x8000L)
  1928  			v += 0x10000L;
  1929  		r = p->from.reg;
  1930  		if(r == NREG)
  1931  			r = o->param;
  1932  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  1933  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  1934  		break;
  1935  
  1936  	case 37:	/* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
  1937  		v = regoff(ctxt, &p->from);
  1938  		if(v & 0x8000L)
  1939  			v += 0x10000L;
  1940  		r = p->from.reg;
  1941  		if(r == NREG)
  1942  			r = o->param;
  1943  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  1944  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  1945  		o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  1946  		break;
  1947  
  1948  	case 40:	/* word */
  1949  		o1 = regoff(ctxt, &p->from);
  1950  		break;
  1951  
  1952  	case 41:	/* stswi */
  1953  		o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
  1954  		break;
  1955  
  1956  	case 42:	/* lswi */
  1957  		o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
  1958  		break;
  1959  
  1960  	case 43:	/* unary indexed source: dcbf (b); dcbf (a+b) */
  1961  		r = p->reg;
  1962  		if(r == NREG)
  1963  			r = 0;
  1964  		o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg);
  1965  		break;
  1966  
  1967  	case 44:	/* indexed store */
  1968  		r = p->reg;
  1969  		if(r == NREG)
  1970  			r = 0;
  1971  		o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg);
  1972  		break;
  1973  	case 45:	/* indexed load */
  1974  		r = p->reg;
  1975  		if(r == NREG)
  1976  			r = 0;
  1977  		o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg);
  1978  		break;
  1979  
  1980  	case 46:	/* plain op */
  1981  		o1 = oprrr(ctxt, p->as);
  1982  		break;
  1983  
  1984  	case 47:	/* op Ra, Rd; also op [Ra,] Rd */
  1985  		r = p->from.reg;
  1986  		if(r == NREG)
  1987  			r = p->to.reg;
  1988  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
  1989  		break;
  1990  
  1991  	case 48:	/* op Rs, Ra */
  1992  		r = p->from.reg;
  1993  		if(r == NREG)
  1994  			r = p->to.reg;
  1995  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
  1996  		break;
  1997  
  1998  	case 49:	/* op Rb; op $n, Rb */
  1999  		if(p->from.type != D_REG){	/* tlbie $L, rB */
  2000  			v = regoff(ctxt, &p->from) & 1;
  2001  			o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21);
  2002  		}else
  2003  			o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg);
  2004  		break;
  2005  
  2006  	case 50:	/* rem[u] r1[,r2],r3 */
  2007  		r = p->reg;
  2008  		if(r == NREG)
  2009  			r = p->to.reg;
  2010  		v = oprrr(ctxt, p->as);
  2011  		t = v & ((1<<10)|1);	/* OE|Rc */
  2012  		o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
  2013  		o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
  2014  		o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
  2015  		if(p->as == AREMU) {
  2016  			o4 = o3;
  2017  			/* Clear top 32 bits */
  2018  			o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5);
  2019  		}
  2020  		break;
  2021  
  2022  	case 51:	/* remd[u] r1[,r2],r3 */
  2023  		r = p->reg;
  2024  		if(r == NREG)
  2025  			r = p->to.reg;
  2026  		v = oprrr(ctxt, p->as);
  2027  		t = v & ((1<<10)|1);	/* OE|Rc */
  2028  		o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
  2029  		o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg);
  2030  		o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
  2031  		break;
  2032  
  2033  	case 52:	/* mtfsbNx cr(n) */
  2034  		v = regoff(ctxt, &p->from)&31L;
  2035  		o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0);
  2036  		break;
  2037  
  2038  	case 53:	/* mffsX ,fr1 */
  2039  		o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
  2040  		break;
  2041  
  2042  	case 54:	/* mov msr,r1; mov r1, msr*/
  2043  		if(oclass(p->from) == C_REG){
  2044  			if(p->as == AMOVD)
  2045  				o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0);
  2046  			else
  2047  				o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
  2048  		}else
  2049  			o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
  2050  		break;
  2051  
  2052  	case 55:	/* op Rb, Rd */
  2053  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg);
  2054  		break;
  2055  
  2056  	case 56:	/* sra $sh,[s,]a; srd $sh,[s,]a */
  2057  		v = regoff(ctxt, &p->from);
  2058  		r = p->reg;
  2059  		if(r == NREG)
  2060  			r = p->to.reg;
  2061  		o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L);
  2062  		if(p->as == ASRAD && (v&0x20))
  2063  			o1 |= 1<<1;	/* mb[5] */
  2064  		break;
  2065  
  2066  	case 57:	/* slw $sh,[s,]a -> rlwinm ... */
  2067  		v = regoff(ctxt, &p->from);
  2068  		r = p->reg;
  2069  		if(r == NREG)
  2070  			r = p->to.reg;
  2071  		/*
  2072  		 * Let user (gs) shoot himself in the foot. 
  2073  		 * qc has already complained.
  2074  		 *
  2075  		if(v < 0 || v > 31)
  2076  			ctxt->diag("illegal shift %ld\n%P", v, p);
  2077  		 */
  2078  		if(v < 0)
  2079  			v = 0;
  2080  		else if(v > 32)
  2081  			v = 32;
  2082  		if(p->as == ASRW || p->as == ASRWCC) {	/* shift right */
  2083  			mask[0] = v;
  2084  			mask[1] = 31;
  2085  			v = 32-v;
  2086  		} else {
  2087  			mask[0] = 0;
  2088  			mask[1] = 31-v;
  2089  		}
  2090  		o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
  2091  		if(p->as == ASLWCC || p->as == ASRWCC)
  2092  			o1 |= 1;	/* Rc */
  2093  		break;
  2094  
  2095  	case 58:		/* logical $andcon,[s],a */
  2096  		v = regoff(ctxt, &p->from);
  2097  		r = p->reg;
  2098  		if(r == NREG)
  2099  			r = p->to.reg;
  2100  		o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
  2101  		break;
  2102  
  2103  	case 59:	/* or/and $ucon,,r */
  2104  		v = regoff(ctxt, &p->from);
  2105  		r = p->reg;
  2106  		if(r == NREG)
  2107  			r = p->to.reg;
  2108  		o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);	/* oris, xoris, andis */
  2109  		break;
  2110  
  2111  	case 60:	/* tw to,a,b */
  2112  		r = regoff(ctxt, &p->from)&31L;
  2113  		o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg);
  2114  		break;
  2115  
  2116  	case 61:	/* tw to,a,$simm */
  2117  		r = regoff(ctxt, &p->from)&31L;
  2118  		v = regoff(ctxt, &p->to);
  2119  		o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v);
  2120  		break;
  2121  
  2122  	case 62:	/* rlwmi $sh,s,$mask,a */
  2123  		v = regoff(ctxt, &p->from);
  2124  		maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
  2125  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v);
  2126  		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  2127  		break;
  2128  
  2129  	case 63:	/* rlwmi b,s,$mask,a */
  2130  		maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
  2131  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg);
  2132  		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  2133  		break;
  2134  
  2135  	case 64:	/* mtfsf fr[, $m] {,fpcsr} */
  2136  		if(p->from3.type != D_NONE)
  2137  			v = regoff(ctxt, &p->from3)&255L;
  2138  		else
  2139  			v = 255;
  2140  		o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
  2141  		break;
  2142  
  2143  	case 65:	/* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
  2144  		if(p->to.reg == NREG)
  2145  			ctxt->diag("must specify FPSCR(n)\n%P", p);
  2146  		o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12);
  2147  		break;
  2148  
  2149  	case 66:	/* mov spr,r1; mov r1,spr, also dcr */
  2150  		if(p->from.type == D_REG) {
  2151  			r = p->from.reg;
  2152  			v = p->to.offset;
  2153  			if(p->to.type == D_DCR)
  2154  				o1 = OPVCC(31,451,0,0);	/* mtdcr */
  2155  			else
  2156  				o1 = OPVCC(31,467,0,0); /* mtspr */
  2157  		} else {
  2158  			r = p->to.reg;
  2159  			v = p->from.offset;
  2160  			if(p->from.type == D_DCR)
  2161  				o1 = OPVCC(31,323,0,0);	/* mfdcr */
  2162  			else
  2163  				o1 = OPVCC(31,339,0,0);	/* mfspr */
  2164  		}
  2165  		o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
  2166  		break;
  2167  
  2168  	case 67:	/* mcrf crfD,crfS */
  2169  		if(p->from.type != D_CREG || p->from.reg == NREG ||
  2170  		   p->to.type != D_CREG || p->to.reg == NREG)
  2171  			ctxt->diag("illegal CR field number\n%P", p);
  2172  		o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  2173  		break;
  2174  
  2175  	case 68:	/* mfcr rD; mfocrf CRM,rD */
  2176  		if(p->from.type == D_CREG && p->from.reg != NREG){
  2177  			v = 1<<(7-(p->to.reg&7));	/* CR(n) */
  2178  			o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12);	/* new form, mfocrf */
  2179  		}else
  2180  			o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0);	/* old form, whole register */
  2181  		break;
  2182  
  2183  	case 69:	/* mtcrf CRM,rS */
  2184  		if(p->from3.type != D_NONE) {
  2185  			if(p->to.reg != NREG)
  2186  				ctxt->diag("can't use both mask and CR(n)\n%P", p);
  2187  			v = regoff(ctxt, &p->from3) & 0xff;
  2188  		} else {
  2189  			if(p->to.reg == NREG)
  2190  				v = 0xff;	/* CR */
  2191  			else
  2192  				v = 1<<(7-(p->to.reg&7));	/* CR(n) */
  2193  		}
  2194  		o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
  2195  		break;
  2196  
  2197  	case 70:	/* [f]cmp r,r,cr*/
  2198  		if(p->reg == NREG)
  2199  			r = 0;
  2200  		else
  2201  			r = (p->reg&7)<<2;
  2202  		o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg);
  2203  		break;
  2204  
  2205  	case 71:	/* cmp[l] r,i,cr*/
  2206  		if(p->reg == NREG)
  2207  			r = 0;
  2208  		else
  2209  			r = (p->reg&7)<<2;
  2210  		o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff);
  2211  		break;
  2212  
  2213  	case 72:	/* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
  2214  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg);
  2215  		break;
  2216  
  2217  	case 73:	/* mcrfs crfD,crfS */
  2218  		if(p->from.type != D_FPSCR || p->from.reg == NREG ||
  2219  		   p->to.type != D_CREG || p->to.reg == NREG)
  2220  			ctxt->diag("illegal FPSCR/CR field number\n%P", p);
  2221  		o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  2222  		break;
  2223  
  2224  	case 77:	/* syscall $scon, syscall Rx */
  2225  		if(p->from.type == D_CONST) {
  2226  			if(p->from.offset > BIG || p->from.offset < -BIG)
  2227  				ctxt->diag("illegal syscall, sysnum too large: %P", p);
  2228  			o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset);
  2229  		} else if(p->from.type == D_REG) {
  2230  			o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg);
  2231  		} else {
  2232  			ctxt->diag("illegal syscall: %P", p);
  2233  			o1 = 0x7fe00008; // trap always
  2234  		}
  2235  		o2 = oprrr(ctxt, p->as);
  2236  		o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0
  2237  		break;
  2238  
  2239  	case 78:	/* undef */
  2240  		o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed
  2241  			   always to be an illegal instruction."  */
  2242  		break;
  2243  
  2244  	/* relocation operations */
  2245  
  2246  	case 74:
  2247  		v = regoff(ctxt, &p->to);
  2248  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2249  		o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
  2250  		addaddrreloc(ctxt, p->to.sym, &o1, &o2);
  2251  		//if(dlm) reloc(&p->to, p->pc, 1);
  2252  		break;
  2253  
  2254  	case 75:
  2255  		v = regoff(ctxt, &p->from);
  2256  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2257  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  2258  		addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  2259  		//if(dlm) reloc(&p->from, p->pc, 1);
  2260  		break;
  2261  
  2262  	case 76:
  2263  		v = regoff(ctxt, &p->from);
  2264  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2265  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  2266  		addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  2267  		o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  2268  		//if(dlm) reloc(&p->from, p->pc, 1);
  2269  		break;
  2270  
  2271  	}
  2272  
  2273  	out[0] = o1;
  2274  	out[1] = o2;
  2275  	out[2] = o3;
  2276  	out[3] = o4;
  2277  	out[4] = o5;
  2278  	return;
  2279  }
  2280  
  2281  static vlong
  2282  vregoff(Link *ctxt, Addr *a)
  2283  {
  2284  
  2285  	ctxt->instoffset = 0;
  2286  	aclass(ctxt, a);
  2287  	return ctxt->instoffset;
  2288  }
  2289  
  2290  static int32
  2291  regoff(Link *ctxt, Addr *a)
  2292  {
  2293  	return vregoff(ctxt, a);
  2294  }
  2295  
  2296  static int32
  2297  oprrr(Link *ctxt, int a)
  2298  {
  2299  	switch(a) {
  2300  	case AADD:	return OPVCC(31,266,0,0);
  2301  	case AADDCC:	return OPVCC(31,266,0,1);
  2302  	case AADDV:	return OPVCC(31,266,1,0);
  2303  	case AADDVCC:	return OPVCC(31,266,1,1);
  2304  	case AADDC:	return OPVCC(31,10,0,0);
  2305  	case AADDCCC:	return OPVCC(31,10,0,1);
  2306  	case AADDCV:	return OPVCC(31,10,1,0);
  2307  	case AADDCVCC:	return OPVCC(31,10,1,1);
  2308  	case AADDE:	return OPVCC(31,138,0,0);
  2309  	case AADDECC:	return OPVCC(31,138,0,1);
  2310  	case AADDEV:	return OPVCC(31,138,1,0);
  2311  	case AADDEVCC:	return OPVCC(31,138,1,1);
  2312  	case AADDME:	return OPVCC(31,234,0,0);
  2313  	case AADDMECC:	return OPVCC(31,234,0,1);
  2314  	case AADDMEV:	return OPVCC(31,234,1,0);
  2315  	case AADDMEVCC:	return OPVCC(31,234,1,1);
  2316  	case AADDZE:	return OPVCC(31,202,0,0);
  2317  	case AADDZECC:	return OPVCC(31,202,0,1);
  2318  	case AADDZEV:	return OPVCC(31,202,1,0);
  2319  	case AADDZEVCC:	return OPVCC(31,202,1,1);
  2320  
  2321  	case AAND:	return OPVCC(31,28,0,0);
  2322  	case AANDCC:	return OPVCC(31,28,0,1);
  2323  	case AANDN:	return OPVCC(31,60,0,0);
  2324  	case AANDNCC:	return OPVCC(31,60,0,1);
  2325  
  2326  	case ACMP:	return OPVCC(31,0,0,0)|(1<<21);	/* L=1 */
  2327  	case ACMPU:	return OPVCC(31,32,0,0)|(1<<21);
  2328  	case ACMPW:	return OPVCC(31,0,0,0);	/* L=0 */
  2329  	case ACMPWU:	return OPVCC(31,32,0,0);
  2330  
  2331  	case ACNTLZW:	return OPVCC(31,26,0,0);
  2332  	case ACNTLZWCC:	return OPVCC(31,26,0,1);
  2333  	case ACNTLZD:		return OPVCC(31,58,0,0);
  2334  	case ACNTLZDCC:	return OPVCC(31,58,0,1);
  2335  
  2336  	case ACRAND:	return OPVCC(19,257,0,0);
  2337  	case ACRANDN:	return OPVCC(19,129,0,0);
  2338  	case ACREQV:	return OPVCC(19,289,0,0);
  2339  	case ACRNAND:	return OPVCC(19,225,0,0);
  2340  	case ACRNOR:	return OPVCC(19,33,0,0);
  2341  	case ACROR:	return OPVCC(19,449,0,0);
  2342  	case ACRORN:	return OPVCC(19,417,0,0);
  2343  	case ACRXOR:	return OPVCC(19,193,0,0);
  2344  
  2345  	case ADCBF:	return OPVCC(31,86,0,0);
  2346  	case ADCBI:	return OPVCC(31,470,0,0);
  2347  	case ADCBST:	return OPVCC(31,54,0,0);
  2348  	case ADCBT:	return OPVCC(31,278,0,0);
  2349  	case ADCBTST:	return OPVCC(31,246,0,0);
  2350  	case ADCBZ:	return OPVCC(31,1014,0,0);
  2351  
  2352  	case AREM:
  2353  	case ADIVW:	return OPVCC(31,491,0,0);
  2354  	case AREMCC:
  2355  	case ADIVWCC:	return OPVCC(31,491,0,1);
  2356  	case AREMV:
  2357  	case ADIVWV:	return OPVCC(31,491,1,0);
  2358  	case AREMVCC:
  2359  	case ADIVWVCC:	return OPVCC(31,491,1,1);
  2360  	case AREMU:
  2361  	case ADIVWU:	return OPVCC(31,459,0,0);
  2362  	case AREMUCC:
  2363  	case ADIVWUCC:	return OPVCC(31,459,0,1);
  2364  	case AREMUV:
  2365  	case ADIVWUV:	return OPVCC(31,459,1,0);
  2366  	case AREMUVCC:
  2367  	case ADIVWUVCC:	return OPVCC(31,459,1,1);
  2368  
  2369  	case AREMD:
  2370  	case ADIVD:	return OPVCC(31,489,0,0);
  2371  	case AREMDCC:
  2372  	case ADIVDCC:	return OPVCC(31,489,0,1);
  2373  	case AREMDV:
  2374  	case ADIVDV:	return OPVCC(31,489,1,0);
  2375  	case AREMDVCC:
  2376  	case ADIVDVCC:	return OPVCC(31,489,1,1);
  2377  	case AREMDU:
  2378  	case ADIVDU:	return OPVCC(31,457,0,0);
  2379  	case AREMDUCC:
  2380  	case ADIVDUCC:	return OPVCC(31,457,0,1);
  2381  	case AREMDUV:
  2382  	case ADIVDUV:	return OPVCC(31,457,1,0);
  2383  	case AREMDUVCC:
  2384  	case ADIVDUVCC:	return OPVCC(31,457,1,1);
  2385  
  2386  	case AEIEIO:	return OPVCC(31,854,0,0);
  2387  
  2388  	case AEQV:	return OPVCC(31,284,0,0);
  2389  	case AEQVCC:	return OPVCC(31,284,0,1);
  2390  
  2391  	case AEXTSB:	return OPVCC(31,954,0,0);
  2392  	case AEXTSBCC:	return OPVCC(31,954,0,1);
  2393  	case AEXTSH:	return OPVCC(31,922,0,0);
  2394  	case AEXTSHCC:	return OPVCC(31,922,0,1);
  2395  	case AEXTSW:	return OPVCC(31,986,0,0);
  2396  	case AEXTSWCC:	return OPVCC(31,986,0,1);
  2397  
  2398  	case AFABS:	return OPVCC(63,264,0,0);
  2399  	case AFABSCC:	return OPVCC(63,264,0,1);
  2400  	case AFADD:	return OPVCC(63,21,0,0);
  2401  	case AFADDCC:	return OPVCC(63,21,0,1);
  2402  	case AFADDS:	return OPVCC(59,21,0,0);
  2403  	case AFADDSCC:	return OPVCC(59,21,0,1);
  2404  	case AFCMPO:	return OPVCC(63,32,0,0);
  2405  	case AFCMPU:	return OPVCC(63,0,0,0);
  2406  	case AFCFID:	return OPVCC(63,846,0,0);
  2407  	case AFCFIDCC:	return OPVCC(63,846,0,1);
  2408  	case AFCTIW:	return OPVCC(63,14,0,0);
  2409  	case AFCTIWCC:	return OPVCC(63,14,0,1);
  2410  	case AFCTIWZ:	return OPVCC(63,15,0,0);
  2411  	case AFCTIWZCC:	return OPVCC(63,15,0,1);
  2412  	case AFCTID:	return OPVCC(63,814,0,0);
  2413  	case AFCTIDCC:	return OPVCC(63,814,0,1);
  2414  	case AFCTIDZ:	return OPVCC(63,815,0,0);
  2415  	case AFCTIDZCC:	return OPVCC(63,815,0,1);
  2416  	case AFDIV:	return OPVCC(63,18,0,0);
  2417  	case AFDIVCC:	return OPVCC(63,18,0,1);
  2418  	case AFDIVS:	return OPVCC(59,18,0,0);
  2419  	case AFDIVSCC:	return OPVCC(59,18,0,1);
  2420  	case AFMADD:	return OPVCC(63,29,0,0);
  2421  	case AFMADDCC:	return OPVCC(63,29,0,1);
  2422  	case AFMADDS:	return OPVCC(59,29,0,0);
  2423  	case AFMADDSCC:	return OPVCC(59,29,0,1);
  2424  	case AFMOVS:
  2425  	case AFMOVD:	return OPVCC(63,72,0,0);	/* load */
  2426  	case AFMOVDCC:	return OPVCC(63,72,0,1);
  2427  	case AFMSUB:	return OPVCC(63,28,0,0);
  2428  	case AFMSUBCC:	return OPVCC(63,28,0,1);
  2429  	case AFMSUBS:	return OPVCC(59,28,0,0);
  2430  	case AFMSUBSCC:	return OPVCC(59,28,0,1);
  2431  	case AFMUL:	return OPVCC(63,25,0,0);
  2432  	case AFMULCC:	return OPVCC(63,25,0,1);
  2433  	case AFMULS:	return OPVCC(59,25,0,0);
  2434  	case AFMULSCC:	return OPVCC(59,25,0,1);
  2435  	case AFNABS:	return OPVCC(63,136,0,0);
  2436  	case AFNABSCC:	return OPVCC(63,136,0,1);
  2437  	case AFNEG:	return OPVCC(63,40,0,0);
  2438  	case AFNEGCC:	return OPVCC(63,40,0,1);
  2439  	case AFNMADD:	return OPVCC(63,31,0,0);
  2440  	case AFNMADDCC:	return OPVCC(63,31,0,1);
  2441  	case AFNMADDS:	return OPVCC(59,31,0,0);
  2442  	case AFNMADDSCC:	return OPVCC(59,31,0,1);
  2443  	case AFNMSUB:	return OPVCC(63,30,0,0);
  2444  	case AFNMSUBCC:	return OPVCC(63,30,0,1);
  2445  	case AFNMSUBS:	return OPVCC(59,30,0,0);
  2446  	case AFNMSUBSCC:	return OPVCC(59,30,0,1);
  2447  	case AFRES:	return OPVCC(59,24,0,0);
  2448  	case AFRESCC:	return OPVCC(59,24,0,1);
  2449  	case AFRSP:	return OPVCC(63,12,0,0);
  2450  	case AFRSPCC:	return OPVCC(63,12,0,1);
  2451  	case AFRSQRTE:	return OPVCC(63,26,0,0);
  2452  	case AFRSQRTECC:	return OPVCC(63,26,0,1);
  2453  	case AFSEL:	return OPVCC(63,23,0,0);
  2454  	case AFSELCC:	return OPVCC(63,23,0,1);
  2455  	case AFSQRT:	return OPVCC(63,22,0,0);
  2456  	case AFSQRTCC:	return OPVCC(63,22,0,1);
  2457  	case AFSQRTS:	return OPVCC(59,22,0,0);
  2458  	case AFSQRTSCC:	return OPVCC(59,22,0,1);
  2459  	case AFSUB:	return OPVCC(63,20,0,0);
  2460  	case AFSUBCC:	return OPVCC(63,20,0,1);
  2461  	case AFSUBS:	return OPVCC(59,20,0,0);
  2462  	case AFSUBSCC:	return OPVCC(59,20,0,1);
  2463  
  2464  	case AICBI:	return OPVCC(31,982,0,0);
  2465  	case AISYNC:	return OPVCC(19,150,0,0);
  2466  
  2467  	case AMTFSB0:	return OPVCC(63,70,0,0);
  2468  	case AMTFSB0CC:	return OPVCC(63,70,0,1);
  2469  	case AMTFSB1:	return OPVCC(63,38,0,0);
  2470  	case AMTFSB1CC:	return OPVCC(63,38,0,1);
  2471  
  2472  	case AMULHW:	return OPVCC(31,75,0,0);
  2473  	case AMULHWCC:	return OPVCC(31,75,0,1);
  2474  	case AMULHWU:	return OPVCC(31,11,0,0);
  2475  	case AMULHWUCC:	return OPVCC(31,11,0,1);
  2476  	case AMULLW:	return OPVCC(31,235,0,0);
  2477  	case AMULLWCC:	return OPVCC(31,235,0,1);
  2478  	case AMULLWV:	return OPVCC(31,235,1,0);
  2479  	case AMULLWVCC:	return OPVCC(31,235,1,1);
  2480  
  2481  	case AMULHD:	return OPVCC(31,73,0,0);
  2482  	case AMULHDCC:	return OPVCC(31,73,0,1);
  2483  	case AMULHDU:	return OPVCC(31,9,0,0);
  2484  	case AMULHDUCC:	return OPVCC(31,9,0,1);
  2485  	case AMULLD:	return OPVCC(31,233,0,0);
  2486  	case AMULLDCC:	return OPVCC(31,233,0,1);
  2487  	case AMULLDV:	return OPVCC(31,233,1,0);
  2488  	case AMULLDVCC:	return OPVCC(31,233,1,1);
  2489  
  2490  	case ANAND:	return OPVCC(31,476,0,0);
  2491  	case ANANDCC:	return OPVCC(31,476,0,1);
  2492  	case ANEG:	return OPVCC(31,104,0,0);
  2493  	case ANEGCC:	return OPVCC(31,104,0,1);
  2494  	case ANEGV:	return OPVCC(31,104,1,0);
  2495  	case ANEGVCC:	return OPVCC(31,104,1,1);
  2496  	case ANOR:	return OPVCC(31,124,0,0);
  2497  	case ANORCC:	return OPVCC(31,124,0,1);
  2498  	case AOR:	return OPVCC(31,444,0,0);
  2499  	case AORCC:	return OPVCC(31,444,0,1);
  2500  	case AORN:	return OPVCC(31,412,0,0);
  2501  	case AORNCC:	return OPVCC(31,412,0,1);
  2502  
  2503  	case ARFI:	return OPVCC(19,50,0,0);
  2504  	case ARFCI:	return OPVCC(19,51,0,0);
  2505  	case ARFID:	return OPVCC(19,18,0,0);
  2506  	case AHRFID: return OPVCC(19,274,0,0);
  2507  
  2508  	case ARLWMI:	return OPVCC(20,0,0,0);
  2509  	case ARLWMICC: return OPVCC(20,0,0,1);
  2510  	case ARLWNM:	return OPVCC(23,0,0,0);
  2511  	case ARLWNMCC:	return OPVCC(23,0,0,1);
  2512  
  2513  	case ARLDCL:	return OPVCC(30,8,0,0);
  2514  	case ARLDCR:	return OPVCC(30,9,0,0);
  2515  
  2516  	case ASYSCALL:	return OPVCC(17,1,0,0);
  2517  
  2518  	case ASLW:	return OPVCC(31,24,0,0);
  2519  	case ASLWCC:	return OPVCC(31,24,0,1);
  2520  	case ASLD:	return OPVCC(31,27,0,0);
  2521  	case ASLDCC:	return OPVCC(31,27,0,1);
  2522  
  2523  	case ASRAW:	return OPVCC(31,792,0,0);
  2524  	case ASRAWCC:	return OPVCC(31,792,0,1);
  2525  	case ASRAD:	return OPVCC(31,794,0,0);
  2526  	case ASRADCC:	return OPVCC(31,794,0,1);
  2527  
  2528  	case ASRW:	return OPVCC(31,536,0,0);
  2529  	case ASRWCC:	return OPVCC(31,536,0,1);
  2530  	case ASRD:	return OPVCC(31,539,0,0);
  2531  	case ASRDCC:	return OPVCC(31,539,0,1);
  2532  
  2533  	case ASUB:	return OPVCC(31,40,0,0);
  2534  	case ASUBCC:	return OPVCC(31,40,0,1);
  2535  	case ASUBV:	return OPVCC(31,40,1,0);
  2536  	case ASUBVCC:	return OPVCC(31,40,1,1);
  2537  	case ASUBC:	return OPVCC(31,8,0,0);
  2538  	case ASUBCCC:	return OPVCC(31,8,0,1);
  2539  	case ASUBCV:	return OPVCC(31,8,1,0);
  2540  	case ASUBCVCC:	return OPVCC(31,8,1,1);
  2541  	case ASUBE:	return OPVCC(31,136,0,0);
  2542  	case ASUBECC:	return OPVCC(31,136,0,1);
  2543  	case ASUBEV:	return OPVCC(31,136,1,0);
  2544  	case ASUBEVCC:	return OPVCC(31,136,1,1);
  2545  	case ASUBME:	return OPVCC(31,232,0,0);
  2546  	case ASUBMECC:	return OPVCC(31,232,0,1);
  2547  	case ASUBMEV:	return OPVCC(31,232,1,0);
  2548  	case ASUBMEVCC:	return OPVCC(31,232,1,1);
  2549  	case ASUBZE:	return OPVCC(31,200,0,0);
  2550  	case ASUBZECC:	return OPVCC(31,200,0,1);
  2551  	case ASUBZEV:	return OPVCC(31,200,1,0);
  2552  	case ASUBZEVCC:	return OPVCC(31,200,1,1);
  2553  
  2554  	case ASYNC:	return OPVCC(31,598,0,0);
  2555  	case APTESYNC:	return OPVCC(31,598,0,0) | (2<<21);
  2556  
  2557  	case ATLBIE:	return OPVCC(31,306,0,0);
  2558  	case ATLBIEL:	return OPVCC(31,274,0,0);
  2559  	case ATLBSYNC:	return OPVCC(31,566,0,0);
  2560  	case ASLBIA:	return OPVCC(31,498,0,0);
  2561  	case ASLBIE:	return OPVCC(31,434,0,0);
  2562  	case ASLBMFEE:	return OPVCC(31,915,0,0);
  2563  	case ASLBMFEV:	return OPVCC(31,851,0,0);
  2564  	case ASLBMTE:		return OPVCC(31,402,0,0);
  2565  
  2566  	case ATW:	return OPVCC(31,4,0,0);
  2567  	case ATD:	return OPVCC(31,68,0,0);
  2568  
  2569  	case AXOR:	return OPVCC(31,316,0,0);
  2570  	case AXORCC:	return OPVCC(31,316,0,1);
  2571  	}
  2572  	ctxt->diag("bad r/r opcode %A", a);
  2573  	return 0;
  2574  }
  2575  
  2576  static int32
  2577  opirr(Link *ctxt, int a)
  2578  {
  2579  	switch(a) {
  2580  	case AADD:	return OPVCC(14,0,0,0);
  2581  	case AADDC:	return OPVCC(12,0,0,0);
  2582  	case AADDCCC:	return OPVCC(13,0,0,0);
  2583  	case AADD+AEND:	return OPVCC(15,0,0,0);		/* ADDIS/CAU */
  2584  
  2585  	case AANDCC:	return OPVCC(28,0,0,0);
  2586  	case AANDCC+AEND:	return OPVCC(29,0,0,0);		/* ANDIS./ANDIU. */
  2587  
  2588  	case ABR:	return OPVCC(18,0,0,0);
  2589  	case ABL:	return OPVCC(18,0,0,0) | 1;
  2590  	case ADUFFZERO:	return OPVCC(18,0,0,0) | 1;
  2591  	case ADUFFCOPY:	return OPVCC(18,0,0,0) | 1;
  2592  	case ABC:	return OPVCC(16,0,0,0);
  2593  	case ABCL:	return OPVCC(16,0,0,0) | 1;
  2594  
  2595  	case ABEQ:	return AOP_RRR(16<<26,12,2,0);
  2596  	case ABGE:	return AOP_RRR(16<<26,4,0,0);
  2597  	case ABGT:	return AOP_RRR(16<<26,12,1,0);
  2598  	case ABLE:	return AOP_RRR(16<<26,4,1,0);
  2599  	case ABLT:	return AOP_RRR(16<<26,12,0,0);
  2600  	case ABNE:	return AOP_RRR(16<<26,4,2,0);
  2601  	case ABVC:	return AOP_RRR(16<<26,4,3,0);
  2602  	case ABVS:	return AOP_RRR(16<<26,12,3,0);
  2603  
  2604  	case ACMP:	return OPVCC(11,0,0,0)|(1<<21);	/* L=1 */
  2605  	case ACMPU:	return OPVCC(10,0,0,0)|(1<<21);
  2606  	case ACMPW:	return OPVCC(11,0,0,0);	/* L=0 */
  2607  	case ACMPWU:	return OPVCC(10,0,0,0);
  2608  	case ALSW:	return OPVCC(31,597,0,0);
  2609  
  2610  	case AMULLW:	return OPVCC(7,0,0,0);
  2611  
  2612  	case AOR:	return OPVCC(24,0,0,0);
  2613  	case AOR+AEND:	return OPVCC(25,0,0,0);		/* ORIS/ORIU */
  2614  
  2615  	case ARLWMI:	return OPVCC(20,0,0,0);		/* rlwimi */
  2616  	case ARLWMICC:	return OPVCC(20,0,0,1);
  2617  	case ARLDMI:	return OPVCC(30,0,0,0) | (3<<2);	/* rldimi */
  2618  	case ARLDMICC:	return OPVCC(30,0,0,1) | (3<<2);
  2619  
  2620  	case ARLWNM:	return OPVCC(21,0,0,0);		/* rlwinm */
  2621  	case ARLWNMCC:	return OPVCC(21,0,0,1);
  2622  
  2623  	case ARLDCL:	return OPVCC(30,0,0,0);		/* rldicl */
  2624  	case ARLDCLCC:	return OPVCC(30,0,0,1);
  2625  	case ARLDCR:	return OPVCC(30,1,0,0);		/* rldicr */
  2626  	case ARLDCRCC:	return OPVCC(30,1,0,1);
  2627  	case ARLDC:	return OPVCC(30,0,0,0) | (2<<2);
  2628  	case ARLDCCC:	return OPVCC(30,0,0,1) | (2<<2);
  2629  
  2630  	case ASRAW:	return OPVCC(31,824,0,0);
  2631  	case ASRAWCC:	return OPVCC(31,824,0,1);
  2632  	case ASRAD:	return OPVCC(31,(413<<1),0,0);
  2633  	case ASRADCC:	return OPVCC(31,(413<<1),0,1);
  2634  
  2635  	case ASTSW:	return OPVCC(31,725,0,0);
  2636  
  2637  	case ASUBC:	return OPVCC(8,0,0,0);
  2638  
  2639  	case ATW:	return OPVCC(3,0,0,0);
  2640  	case ATD:	return OPVCC(2,0,0,0);
  2641  
  2642  	case AXOR:	return OPVCC(26,0,0,0);		/* XORIL */
  2643  	case AXOR+AEND:	return OPVCC(27,0,0,0);		/* XORIU */
  2644  	}
  2645  	ctxt->diag("bad opcode i/r %A", a);
  2646  	return 0;
  2647  }
  2648  
  2649  /*
  2650   * load o(a),d
  2651   */
  2652  static int32
  2653  opload(Link *ctxt, int a)
  2654  {
  2655  	switch(a) {
  2656  	case AMOVD:	return OPVCC(58,0,0,0);	/* ld */
  2657  	case AMOVDU:	return OPVCC(58,0,0,1);	/* ldu */
  2658  	case AMOVWZ:	return OPVCC(32,0,0,0);		/* lwz */
  2659  	case AMOVWZU:	return OPVCC(33,0,0,0);		/* lwzu */
  2660  	case AMOVW:		return OPVCC(58,0,0,0)|(1<<1);	/* lwa */
  2661  	/* no AMOVWU */
  2662  	case AMOVB:
  2663  	case AMOVBZ:	return OPVCC(34,0,0,0);		/* load */
  2664  	case AMOVBU:
  2665  	case AMOVBZU:	return OPVCC(35,0,0,0);
  2666  	case AFMOVD:	return OPVCC(50,0,0,0);
  2667  	case AFMOVDU:	return OPVCC(51,0,0,0);
  2668  	case AFMOVS:	return OPVCC(48,0,0,0);
  2669  	case AFMOVSU:	return OPVCC(49,0,0,0);
  2670  	case AMOVH:	return OPVCC(42,0,0,0);
  2671  	case AMOVHU:	return OPVCC(43,0,0,0);
  2672  	case AMOVHZ:	return OPVCC(40,0,0,0);
  2673  	case AMOVHZU:	return OPVCC(41,0,0,0);
  2674  	case AMOVMW:	return OPVCC(46,0,0,0);	/* lmw */
  2675  	}
  2676  	ctxt->diag("bad load opcode %A", a);
  2677  	return 0;
  2678  }
  2679  
  2680  /*
  2681   * indexed load a(b),d
  2682   */
  2683  static int32
  2684  oploadx(Link *ctxt, int a)
  2685  {
  2686  	switch(a) {
  2687  	case AMOVWZ: return OPVCC(31,23,0,0);	/* lwzx */
  2688  	case AMOVWZU:	return OPVCC(31,55,0,0); /* lwzux */
  2689  	case AMOVW:	return OPVCC(31,341,0,0);	/* lwax */
  2690  	case AMOVWU:	return OPVCC(31,373,0,0);	/* lwaux */
  2691  	case AMOVB:
  2692  	case AMOVBZ: return OPVCC(31,87,0,0);	/* lbzx */
  2693  	case AMOVBU:
  2694  	case AMOVBZU: return OPVCC(31,119,0,0);	/* lbzux */
  2695  	case AFMOVD:	return OPVCC(31,599,0,0);	/* lfdx */
  2696  	case AFMOVDU:	return OPVCC(31,631,0,0);	/*  lfdux */
  2697  	case AFMOVS:	return OPVCC(31,535,0,0);	/* lfsx */
  2698  	case AFMOVSU:	return OPVCC(31,567,0,0);	/* lfsux */
  2699  	case AMOVH:	return OPVCC(31,343,0,0);	/* lhax */
  2700  	case AMOVHU:	return OPVCC(31,375,0,0);	/* lhaux */
  2701  	case AMOVHBR:	return OPVCC(31,790,0,0);	/* lhbrx */
  2702  	case AMOVWBR:	return OPVCC(31,534,0,0);	/* lwbrx */
  2703  	case AMOVHZ:	return OPVCC(31,279,0,0);	/* lhzx */
  2704  	case AMOVHZU:	return OPVCC(31,311,0,0);	/* lhzux */
  2705  	case AECIWX:	return OPVCC(31,310,0,0);	/* eciwx */
  2706  	case ALWAR:	return OPVCC(31,20,0,0);	/* lwarx */
  2707  	case ALDAR:	return OPVCC(31,84,0,0);
  2708  	case ALSW:	return OPVCC(31,533,0,0);	/* lswx */
  2709  	case AMOVD:	return OPVCC(31,21,0,0);	/* ldx */
  2710  	case AMOVDU:	return OPVCC(31,53,0,0);	/* ldux */
  2711  	}
  2712  	ctxt->diag("bad loadx opcode %A", a);
  2713  	return 0;
  2714  }
  2715  
  2716  /*
  2717   * store s,o(d)
  2718   */
  2719  static int32
  2720  opstore(Link *ctxt, int a)
  2721  {
  2722  	switch(a) {
  2723  	case AMOVB:
  2724  	case AMOVBZ:	return OPVCC(38,0,0,0);	/* stb */
  2725  	case AMOVBU:
  2726  	case AMOVBZU:	return OPVCC(39,0,0,0);	/* stbu */
  2727  	case AFMOVD:	return OPVCC(54,0,0,0);	/* stfd */
  2728  	case AFMOVDU:	return OPVCC(55,0,0,0);	/* stfdu */
  2729  	case AFMOVS:	return OPVCC(52,0,0,0);	/* stfs */
  2730  	case AFMOVSU:	return OPVCC(53,0,0,0);	/* stfsu */
  2731  	case AMOVHZ:
  2732  	case AMOVH:	return OPVCC(44,0,0,0);	/* sth */
  2733  	case AMOVHZU:
  2734  	case AMOVHU:	return OPVCC(45,0,0,0);	/* sthu */
  2735  	case AMOVMW:	return OPVCC(47,0,0,0);	/* stmw */
  2736  	case ASTSW:	return OPVCC(31,725,0,0);	/* stswi */
  2737  	case AMOVWZ:
  2738  	case AMOVW:	return OPVCC(36,0,0,0);	/* stw */
  2739  	case AMOVWZU:
  2740  	case AMOVWU:	return OPVCC(37,0,0,0);	/* stwu */
  2741  	case AMOVD:	return OPVCC(62,0,0,0);	/* std */
  2742  	case AMOVDU:	return OPVCC(62,0,0,1);	/* stdu */
  2743  	}
  2744  	ctxt->diag("unknown store opcode %A", a);
  2745  	return 0;
  2746  }
  2747  
  2748  /*
  2749   * indexed store s,a(b)
  2750   */
  2751  static int32
  2752  opstorex(Link *ctxt, int a)
  2753  {
  2754  	switch(a) {
  2755  	case AMOVB:
  2756  	case AMOVBZ:	return OPVCC(31,215,0,0);	/* stbx */
  2757  	case AMOVBU:
  2758  	case AMOVBZU:	return OPVCC(31,247,0,0);	/* stbux */
  2759  	case AFMOVD:	return OPVCC(31,727,0,0);	/* stfdx */
  2760  	case AFMOVDU:	return OPVCC(31,759,0,0);	/* stfdux */
  2761  	case AFMOVS:	return OPVCC(31,663,0,0);	/* stfsx */
  2762  	case AFMOVSU:	return OPVCC(31,695,0,0);	/* stfsux */
  2763  	case AMOVHZ:
  2764  	case AMOVH:	return OPVCC(31,407,0,0);	/* sthx */
  2765  	case AMOVHBR:	return OPVCC(31,918,0,0);	/* sthbrx */
  2766  	case AMOVHZU:
  2767  	case AMOVHU:	return OPVCC(31,439,0,0);	/* sthux */
  2768  	case AMOVWZ:
  2769  	case AMOVW:	return OPVCC(31,151,0,0);	/* stwx */
  2770  	case AMOVWZU:
  2771  	case AMOVWU:	return OPVCC(31,183,0,0);	/* stwux */
  2772  	case ASTSW:	return OPVCC(31,661,0,0);	/* stswx */
  2773  	case AMOVWBR:	return OPVCC(31,662,0,0);	/* stwbrx */
  2774  	case ASTWCCC:	return OPVCC(31,150,0,1);	/* stwcx. */
  2775  	case ASTDCCC:	return OPVCC(31,214,0,1);	/* stwdx. */
  2776  	case AECOWX:	return OPVCC(31,438,0,0);	/* ecowx */
  2777  	case AMOVD:	return OPVCC(31,149,0,0);	/* stdx */
  2778  	case AMOVDU:	return OPVCC(31,181,0,0);	/* stdux */
  2779  	}
  2780  	ctxt->diag("unknown storex opcode %A", a);
  2781  	return 0;
  2782  }
  2783