github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/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  				if(isint32(ctxt->instoffset))
   687  					return C_LACON;
   688  				return C_DACON;
   689  			}
   690  		consize:
   691  			if(ctxt->instoffset >= 0) {
   692  				if(ctxt->instoffset == 0)
   693  					return C_ZCON;
   694  				if(ctxt->instoffset <= 0x7fff)
   695  					return C_SCON;
   696  				if(ctxt->instoffset <= 0xffff)
   697  					return C_ANDCON;
   698  				if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset))	/* && (instoffset & (1<<31)) == 0) */
   699  					return C_UCON;
   700  				if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset))
   701  					return C_LCON;
   702  				return C_DCON;
   703  			}
   704  			if(ctxt->instoffset >= -0x8000)
   705  				return C_ADDCON;
   706  			if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset))
   707  				return C_UCON;
   708  			if(isint32(ctxt->instoffset))
   709  				return C_LCON;
   710  			return C_DCON;
   711  
   712  		case D_EXTERN:
   713  		case D_STATIC:
   714  			s = a->sym;
   715  			if(s == nil)
   716  				break;
   717  			if(s->type == SCONST) {
   718  				ctxt->instoffset = s->value + a->offset;
   719  				goto consize;
   720  			}
   721  			ctxt->instoffset = s->value + a->offset;
   722  			/* not sure why this barfs */
   723  			return C_LCON;
   724  
   725  		case D_AUTO:
   726  			ctxt->instoffset = ctxt->autosize + a->offset;
   727  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   728  				return C_SACON;
   729  			return C_LACON;
   730  
   731  		case D_PARAM:
   732  			ctxt->instoffset = ctxt->autosize + a->offset + 8L;
   733  			if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
   734  				return C_SACON;
   735  			return C_LACON;
   736  		}
   737  		return C_GOK;
   738  
   739  	case D_BRANCH:
   740  		return C_SBRA;
   741  	}
   742  	return C_GOK;
   743  }
   744  
   745  static void
   746  prasm(Prog *p)
   747  {
   748  	print("%P\n", p);
   749  }
   750  
   751  static Optab*
   752  oplook(Link *ctxt, Prog *p)
   753  {
   754  	int a1, a2, a3, a4, r;
   755  	uchar *c1, *c3, *c4;
   756  	Optab *o, *e;
   757  
   758  	a1 = p->optab;
   759  	if(a1)
   760  		return optab+(a1-1);
   761  	a1 = p->from.class;
   762  	if(a1 == 0) {
   763  		a1 = aclass(ctxt, &p->from) + 1;
   764  		p->from.class = a1;
   765  	}
   766  	a1--;
   767  	a3 = p->from3.class;
   768  	if(a3 == 0) {
   769  		a3 = aclass(ctxt, &p->from3) + 1;
   770  		p->from3.class = a3;
   771  	}
   772  	a3--;
   773  	a4 = p->to.class;
   774  	if(a4 == 0) {
   775  		a4 = aclass(ctxt, &p->to) + 1;
   776  		p->to.class = a4;
   777  	}
   778  	a4--;
   779  	a2 = C_NONE;
   780  	if(p->reg != NREG)
   781  		a2 = C_REG;
   782  //print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
   783  	r = p->as;
   784  	o = oprange[r].start;
   785  	if(o == 0)
   786  		o = oprange[r].stop; /* just generate an error */
   787  	e = oprange[r].stop;
   788  	c1 = xcmp[a1];
   789  	c3 = xcmp[a3];
   790  	c4 = xcmp[a4];
   791  	for(; o<e; o++)
   792  		if(o->a2 == a2)
   793  		if(c1[o->a1])
   794  		if(c3[o->a3])
   795  		if(c4[o->a4]) {
   796  			p->optab = (o-optab)+1;
   797  			return o;
   798  		}
   799  	ctxt->diag("illegal combination %A %^ %^ %^ %^",
   800  		p->as, a1, a2, a3, a4);
   801  	prasm(p);
   802  	if(o == 0)
   803  		o = optab;
   804  	return o;
   805  }
   806  
   807  static int
   808  cmp(int a, int b)
   809  {
   810  
   811  	if(a == b)
   812  		return 1;
   813  	switch(a) {
   814  	case C_LCON:
   815  		if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON)
   816  			return 1;
   817  		break;
   818  	case C_ADDCON:
   819  		if(b == C_ZCON || b == C_SCON)
   820  			return 1;
   821  		break;
   822  	case C_ANDCON:
   823  		if(b == C_ZCON || b == C_SCON)
   824  			return 1;
   825  		break;
   826  	case C_SPR:
   827  		if(b == C_LR || b == C_XER || b == C_CTR)
   828  			return 1;
   829  		break;
   830  	case C_UCON:
   831  		if(b == C_ZCON)
   832  			return 1;
   833  		break;
   834  	case C_SCON:
   835  		if(b == C_ZCON)
   836  			return 1;
   837  		break;
   838  	case C_LACON:
   839  		if(b == C_SACON)
   840  			return 1;
   841  		break;
   842  	case C_LBRA:
   843  		if(b == C_SBRA)
   844  			return 1;
   845  		break;
   846  	case C_LEXT:
   847  		if(b == C_SEXT)
   848  			return 1;
   849  		break;
   850  	case C_LAUTO:
   851  		if(b == C_SAUTO)
   852  			return 1;
   853  		break;
   854  	case C_REG:
   855  		if(b == C_ZCON)
   856  			return r0iszero;
   857  		break;
   858  	case C_LOREG:
   859  		if(b == C_ZOREG || b == C_SOREG)
   860  			return 1;
   861  		break;
   862  	case C_SOREG:
   863  		if(b == C_ZOREG)
   864  			return 1;
   865  		break;
   866  
   867  	case C_ANY:
   868  		return 1;
   869  	}
   870  	return 0;
   871  }
   872  
   873  static int
   874  ocmp(const void *a1, const void *a2)
   875  {
   876  	const Optab *p1, *p2;
   877  	int n;
   878  
   879  	p1 = a1;
   880  	p2 = a2;
   881  	n = p1->as - p2->as;
   882  	if(n)
   883  		return n;
   884  	n = p1->a1 - p2->a1;
   885  	if(n)
   886  		return n;
   887  	n = p1->a2 - p2->a2;
   888  	if(n)
   889  		return n;
   890  	n = p1->a3 - p2->a3;
   891  	if(n)
   892  		return n;
   893  	n = p1->a4 - p2->a4;
   894  	if(n)
   895  		return n;
   896  	return 0;
   897  }
   898  
   899  static void
   900  buildop(Link *ctxt)
   901  {
   902  	int i, n, r;
   903  
   904  	for(i=0; i<C_NCLASS; i++)
   905  		for(n=0; n<C_NCLASS; n++)
   906  			xcmp[i][n] = cmp(n, i);
   907  	for(n=0; optab[n].as != AXXX; n++)
   908  		;
   909  	qsort(optab, n, sizeof(optab[0]), ocmp);
   910  	for(i=0; i<n; i++) {
   911  		r = optab[i].as;
   912  		oprange[r].start = optab+i;
   913  		while(optab[i].as == r)
   914  			i++;
   915  		oprange[r].stop = optab+i;
   916  		i--;
   917  		
   918  		switch(r)
   919  		{
   920  		default:
   921  			ctxt->diag("unknown op in build: %A", r);
   922  			sysfatal("bad code");
   923  		case ADCBF:	/* unary indexed: op (b+a); op (b) */
   924  			oprange[ADCBI] = oprange[r];
   925  			oprange[ADCBST] = oprange[r];
   926  			oprange[ADCBT] = oprange[r];
   927  			oprange[ADCBTST] = oprange[r];
   928  			oprange[ADCBZ] = oprange[r];
   929  			oprange[AICBI] = oprange[r];
   930  			break;
   931  		case AECOWX:	/* indexed store: op s,(b+a); op s,(b) */
   932  			oprange[ASTWCCC] = oprange[r];
   933  			oprange[ASTDCCC] = oprange[r];
   934  			break;
   935  		case AREM:	/* macro */
   936  			oprange[AREMCC] = oprange[r];
   937  			oprange[AREMV] = oprange[r];
   938  			oprange[AREMVCC] = oprange[r];
   939  			break;
   940  		case AREMU:
   941  			oprange[AREMU] = oprange[r];
   942  			oprange[AREMUCC] = oprange[r];
   943  			oprange[AREMUV] = oprange[r];
   944  			oprange[AREMUVCC] = oprange[r];
   945  			break;
   946  		case AREMD:
   947  			oprange[AREMDCC] = oprange[r];
   948  			oprange[AREMDV] = oprange[r];
   949  			oprange[AREMDVCC] = oprange[r];
   950  			break;
   951  		case AREMDU:
   952  			oprange[AREMDU] = oprange[r];
   953  			oprange[AREMDUCC] = oprange[r];
   954  			oprange[AREMDUV] = oprange[r];
   955  			oprange[AREMDUVCC] = oprange[r];
   956  			break;
   957  		case ADIVW:	/* op Rb[,Ra],Rd */
   958  			oprange[AMULHW] = oprange[r];
   959  			oprange[AMULHWCC] = oprange[r];
   960  			oprange[AMULHWU] = oprange[r];
   961  			oprange[AMULHWUCC] = oprange[r];
   962  			oprange[AMULLWCC] = oprange[r];
   963  			oprange[AMULLWVCC] = oprange[r];
   964  			oprange[AMULLWV] = oprange[r];
   965  			oprange[ADIVWCC] = oprange[r];
   966  			oprange[ADIVWV] = oprange[r];
   967  			oprange[ADIVWVCC] = oprange[r];
   968  			oprange[ADIVWU] = oprange[r];
   969  			oprange[ADIVWUCC] = oprange[r];
   970  			oprange[ADIVWUV] = oprange[r];
   971  			oprange[ADIVWUVCC] = oprange[r];
   972  			oprange[AADDCC] = oprange[r];
   973  			oprange[AADDCV] = oprange[r];
   974  			oprange[AADDCVCC] = oprange[r];
   975  			oprange[AADDV] = oprange[r];
   976  			oprange[AADDVCC] = oprange[r];
   977  			oprange[AADDE] = oprange[r];
   978  			oprange[AADDECC] = oprange[r];
   979  			oprange[AADDEV] = oprange[r];
   980  			oprange[AADDEVCC] = oprange[r];
   981  			oprange[ACRAND] = oprange[r];
   982  			oprange[ACRANDN] = oprange[r];
   983  			oprange[ACREQV] = oprange[r];
   984  			oprange[ACRNAND] = oprange[r];
   985  			oprange[ACRNOR] = oprange[r];
   986  			oprange[ACROR] = oprange[r];
   987  			oprange[ACRORN] = oprange[r];
   988  			oprange[ACRXOR] = oprange[r];
   989  			oprange[AMULHD] = oprange[r];
   990  			oprange[AMULHDCC] = oprange[r];
   991  			oprange[AMULHDU] = oprange[r];
   992  			oprange[AMULHDUCC] = oprange[r];
   993  			oprange[AMULLD] = oprange[r];
   994  			oprange[AMULLDCC] = oprange[r];
   995  			oprange[AMULLDVCC] = oprange[r];
   996  			oprange[AMULLDV] = oprange[r];
   997  			oprange[ADIVD] = oprange[r];
   998  			oprange[ADIVDCC] = oprange[r];
   999  			oprange[ADIVDVCC] = oprange[r];
  1000  			oprange[ADIVDV] = oprange[r];
  1001  			oprange[ADIVDU] = oprange[r];
  1002  			oprange[ADIVDUCC] = oprange[r];
  1003  			oprange[ADIVDUVCC] = oprange[r];
  1004  			oprange[ADIVDUCC] = oprange[r];
  1005  			break;
  1006  		case AMOVBZ:	/* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
  1007  			oprange[AMOVH] = oprange[r];
  1008  			oprange[AMOVHZ] = oprange[r];
  1009  			break;
  1010  		case AMOVBZU:	/* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
  1011  			oprange[AMOVHU] = oprange[r];
  1012  			oprange[AMOVHZU] = oprange[r];
  1013  			oprange[AMOVWU] = oprange[r];
  1014  			oprange[AMOVWZU] = oprange[r];
  1015  			oprange[AMOVDU] = oprange[r];
  1016  			oprange[AMOVMW] = oprange[r];
  1017  			break;
  1018  		case AAND:	/* logical op Rb,Rs,Ra; no literal */
  1019  			oprange[AANDN] = oprange[r];
  1020  			oprange[AANDNCC] = oprange[r];
  1021  			oprange[AEQV] = oprange[r];
  1022  			oprange[AEQVCC] = oprange[r];
  1023  			oprange[ANAND] = oprange[r];
  1024  			oprange[ANANDCC] = oprange[r];
  1025  			oprange[ANOR] = oprange[r];
  1026  			oprange[ANORCC] = oprange[r];
  1027  			oprange[AORCC] = oprange[r];
  1028  			oprange[AORN] = oprange[r];
  1029  			oprange[AORNCC] = oprange[r];
  1030  			oprange[AXORCC] = oprange[r];
  1031  			break;
  1032  		case AADDME:	/* op Ra, Rd */
  1033  			oprange[AADDMECC] = oprange[r];
  1034  			oprange[AADDMEV] = oprange[r];
  1035  			oprange[AADDMEVCC] = oprange[r];
  1036  			oprange[AADDZE] = oprange[r];
  1037  			oprange[AADDZECC] = oprange[r];
  1038  			oprange[AADDZEV] = oprange[r];
  1039  			oprange[AADDZEVCC] = oprange[r];
  1040  			oprange[ASUBME] = oprange[r];
  1041  			oprange[ASUBMECC] = oprange[r];
  1042  			oprange[ASUBMEV] = oprange[r];
  1043  			oprange[ASUBMEVCC] = oprange[r];
  1044  			oprange[ASUBZE] = oprange[r];
  1045  			oprange[ASUBZECC] = oprange[r];
  1046  			oprange[ASUBZEV] = oprange[r];
  1047  			oprange[ASUBZEVCC] = oprange[r];
  1048  			break;
  1049  		case AADDC:
  1050  			oprange[AADDCCC] = oprange[r];
  1051  			break;
  1052  		case ABEQ:
  1053  			oprange[ABGE] = oprange[r];
  1054  			oprange[ABGT] = oprange[r];
  1055  			oprange[ABLE] = oprange[r];
  1056  			oprange[ABLT] = oprange[r];
  1057  			oprange[ABNE] = oprange[r];
  1058  			oprange[ABVC] = oprange[r];
  1059  			oprange[ABVS] = oprange[r];
  1060  			break;
  1061  		case ABR:
  1062  			oprange[ABL] = oprange[r];
  1063  			break;
  1064  		case ABC:
  1065  			oprange[ABCL] = oprange[r];
  1066  			break;
  1067  		case AEXTSB:	/* op Rs, Ra */
  1068  			oprange[AEXTSBCC] = oprange[r];
  1069  			oprange[AEXTSH] = oprange[r];
  1070  			oprange[AEXTSHCC] = oprange[r];
  1071  			oprange[ACNTLZW] = oprange[r];
  1072  			oprange[ACNTLZWCC] = oprange[r];
  1073  			oprange[ACNTLZD] = oprange[r];
  1074  			oprange[AEXTSW] = oprange[r];
  1075  			oprange[AEXTSWCC] = oprange[r];
  1076  			oprange[ACNTLZDCC] = oprange[r];
  1077  			break;
  1078  		case AFABS:	/* fop [s,]d */
  1079  			oprange[AFABSCC] = oprange[r];
  1080  			oprange[AFNABS] = oprange[r];
  1081  			oprange[AFNABSCC] = oprange[r];
  1082  			oprange[AFNEG] = oprange[r];
  1083  			oprange[AFNEGCC] = oprange[r];
  1084  			oprange[AFRSP] = oprange[r];
  1085  			oprange[AFRSPCC] = oprange[r];
  1086  			oprange[AFCTIW] = oprange[r];
  1087  			oprange[AFCTIWCC] = oprange[r];
  1088  			oprange[AFCTIWZ] = oprange[r];
  1089  			oprange[AFCTIWZCC] = oprange[r];
  1090  			oprange[AFCTID] = oprange[r];
  1091  			oprange[AFCTIDCC] = oprange[r];
  1092  			oprange[AFCTIDZ] = oprange[r];
  1093  			oprange[AFCTIDZCC] = oprange[r];
  1094  			oprange[AFCFID] = oprange[r];
  1095  			oprange[AFCFIDCC] = oprange[r];
  1096  			oprange[AFRES] = oprange[r];
  1097  			oprange[AFRESCC] = oprange[r];
  1098  			oprange[AFRSQRTE] = oprange[r];
  1099  			oprange[AFRSQRTECC] = oprange[r];
  1100  			oprange[AFSQRT] = oprange[r];
  1101  			oprange[AFSQRTCC] = oprange[r];
  1102  			oprange[AFSQRTS] = oprange[r];
  1103  			oprange[AFSQRTSCC] = oprange[r];
  1104  			break;
  1105  		case AFADD:
  1106  			oprange[AFADDS] = oprange[r];
  1107  			oprange[AFADDCC] = oprange[r];
  1108  			oprange[AFADDSCC] = oprange[r];
  1109  			oprange[AFDIV] = oprange[r];
  1110  			oprange[AFDIVS] = oprange[r];
  1111  			oprange[AFDIVCC] = oprange[r];
  1112  			oprange[AFDIVSCC] = oprange[r];
  1113  			oprange[AFSUB] = oprange[r];
  1114  			oprange[AFSUBS] = oprange[r];
  1115  			oprange[AFSUBCC] = oprange[r];
  1116  			oprange[AFSUBSCC] = oprange[r];
  1117  			break;
  1118  		case AFMADD:
  1119  			oprange[AFMADDCC] = oprange[r];
  1120  			oprange[AFMADDS] = oprange[r];
  1121  			oprange[AFMADDSCC] = oprange[r];
  1122  			oprange[AFMSUB] = oprange[r];
  1123  			oprange[AFMSUBCC] = oprange[r];
  1124  			oprange[AFMSUBS] = oprange[r];
  1125  			oprange[AFMSUBSCC] = oprange[r];
  1126  			oprange[AFNMADD] = oprange[r];
  1127  			oprange[AFNMADDCC] = oprange[r];
  1128  			oprange[AFNMADDS] = oprange[r];
  1129  			oprange[AFNMADDSCC] = oprange[r];
  1130  			oprange[AFNMSUB] = oprange[r];
  1131  			oprange[AFNMSUBCC] = oprange[r];
  1132  			oprange[AFNMSUBS] = oprange[r];
  1133  			oprange[AFNMSUBSCC] = oprange[r];
  1134  			oprange[AFSEL] = oprange[r];
  1135  			oprange[AFSELCC] = oprange[r];
  1136  			break;
  1137  		case AFMUL:
  1138  			oprange[AFMULS] = oprange[r];
  1139  			oprange[AFMULCC] = oprange[r];
  1140  			oprange[AFMULSCC] = oprange[r];
  1141  			break;
  1142  		case AFCMPO:
  1143  			oprange[AFCMPU] = oprange[r];
  1144  			break;
  1145  		case AMTFSB0:
  1146  			oprange[AMTFSB0CC] = oprange[r];
  1147  			oprange[AMTFSB1] = oprange[r];
  1148  			oprange[AMTFSB1CC] = oprange[r];
  1149  			break;
  1150  		case ANEG:	/* op [Ra,] Rd */
  1151  			oprange[ANEGCC] = oprange[r];
  1152  			oprange[ANEGV] = oprange[r];
  1153  			oprange[ANEGVCC] = oprange[r];
  1154  			break;
  1155  		case AOR:	/* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
  1156  			oprange[AXOR] = oprange[r];
  1157  			break;
  1158  		case ASLW:
  1159  			oprange[ASLWCC] = oprange[r];
  1160  			oprange[ASRW] = oprange[r];
  1161  			oprange[ASRWCC] = oprange[r];
  1162  			break;
  1163  		case ASLD:
  1164  			oprange[ASLDCC] = oprange[r];
  1165  			oprange[ASRD] = oprange[r];
  1166  			oprange[ASRDCC] = oprange[r];
  1167  			break;
  1168  		case ASRAW:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
  1169  			oprange[ASRAWCC] = oprange[r];
  1170  			break;
  1171  		case ASRAD:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
  1172  			oprange[ASRADCC] = oprange[r];
  1173  			break;
  1174  		case ASUB:	/* SUB Ra,Rb,Rd => subf Rd,ra,rb */
  1175  			oprange[ASUB] = oprange[r];
  1176  			oprange[ASUBCC] = oprange[r];
  1177  			oprange[ASUBV] = oprange[r];
  1178  			oprange[ASUBVCC] = oprange[r];
  1179  			oprange[ASUBCCC] = oprange[r];
  1180  			oprange[ASUBCV] = oprange[r];
  1181  			oprange[ASUBCVCC] = oprange[r];
  1182  			oprange[ASUBE] = oprange[r];
  1183  			oprange[ASUBECC] = oprange[r];
  1184  			oprange[ASUBEV] = oprange[r];
  1185  			oprange[ASUBEVCC] = oprange[r];
  1186  			break;
  1187  		case ASYNC:
  1188  			oprange[AISYNC] = oprange[r];
  1189  			oprange[APTESYNC] = oprange[r];
  1190  			oprange[ATLBSYNC] = oprange[r];
  1191  			break;
  1192  		case ARLWMI:
  1193  			oprange[ARLWMICC] = oprange[r];
  1194  			oprange[ARLWNM] = oprange[r];
  1195  			oprange[ARLWNMCC] = oprange[r];
  1196  			break;
  1197  		case ARLDMI:
  1198  			oprange[ARLDMICC] = oprange[r];
  1199  			break;
  1200  		case ARLDC:
  1201  			oprange[ARLDCCC] = oprange[r];
  1202  			break;
  1203  		case ARLDCL:
  1204  			oprange[ARLDCR] = oprange[r];
  1205  			oprange[ARLDCLCC] = oprange[r];
  1206  			oprange[ARLDCRCC] = oprange[r];
  1207  			break;
  1208  		case AFMOVD:
  1209  			oprange[AFMOVDCC] = oprange[r];
  1210  			oprange[AFMOVDU] = oprange[r];
  1211  			oprange[AFMOVS] = oprange[r];
  1212  			oprange[AFMOVSU] = oprange[r];
  1213  			break;
  1214  		case AECIWX:
  1215  			oprange[ALWAR] = oprange[r];
  1216  			oprange[ALDAR] = oprange[r];
  1217  			break;
  1218  		case ASYSCALL:	/* just the op; flow of control */
  1219  			oprange[ARFI] = oprange[r];
  1220  			oprange[ARFCI] = oprange[r];
  1221  			oprange[ARFID] = oprange[r];
  1222  			oprange[AHRFID] = oprange[r];
  1223  			break;
  1224  		case AMOVHBR:
  1225  			oprange[AMOVWBR] = oprange[r];
  1226  			break;
  1227  		case ASLBMFEE:
  1228  			oprange[ASLBMFEV] = oprange[r];
  1229  			break;
  1230  		case ATW:
  1231  			oprange[ATD] = oprange[r];
  1232  			break;
  1233  		case ATLBIE:
  1234  			oprange[ASLBIE] = oprange[r];
  1235  			oprange[ATLBIEL] = oprange[r];
  1236  			break;
  1237  		case AEIEIO:
  1238  			oprange[ASLBIA] = oprange[r];
  1239  			break;
  1240  		case ACMP:
  1241  			oprange[ACMPW] = oprange[r];
  1242  			break;
  1243  		case ACMPU:
  1244  			oprange[ACMPWU] = oprange[r];
  1245  			break;
  1246  		case AADD:
  1247  		case AANDCC:	/* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
  1248  		case ALSW:
  1249  		case AMOVW:	/* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
  1250  		case AMOVWZ:	/* load/store/move word with zero extension; move 32-bit literals  */
  1251  		case AMOVD:	/* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
  1252  		case AMOVB:	/* macro: move byte with sign extension */
  1253  		case AMOVBU:	/* macro: move byte with sign extension & update */
  1254  		case AMOVFL:
  1255  		case AMULLW:	/* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
  1256  		case ASUBC:	/* op r1,$s,r3; op r1[,r2],r3 */
  1257  		case ASTSW:
  1258  		case ASLBMTE:
  1259  		case AWORD:
  1260  		case ADWORD:
  1261  		case ANOP:
  1262  		case ATEXT:
  1263  		case AUNDEF:
  1264  		case AUSEFIELD:
  1265  		case AFUNCDATA:
  1266  		case APCDATA:
  1267  		case ADUFFZERO:
  1268  		case ADUFFCOPY:
  1269  			break;
  1270  		}
  1271  	}
  1272  }
  1273  
  1274  #define	OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
  1275  #define	OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
  1276  #define	OP(o,xo) OPVCC((o),(xo),0,0)
  1277  
  1278  /* the order is dest, a/s, b/imm for both arithmetic and logical operations */
  1279  #define	AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  1280  #define	AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
  1281  #define	LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  1282  #define	LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
  1283  #define	OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
  1284  #define	OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
  1285  #define	OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
  1286  #define	OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
  1287  					(((mb)&31L)<<6)|(((me)&31L)<<1))
  1288  
  1289  #define	OP_ADD	OPVCC(31,266,0,0)
  1290  #define	OP_ADDI	OPVCC(14,0,0,0)
  1291  #define	OP_ADDIS OPVCC(15,0,0,0)
  1292  #define	OP_ANDI	OPVCC(28,0,0,0)
  1293  #define	OP_EXTSB	OPVCC(31,954,0,0)
  1294  #define	OP_EXTSH OPVCC(31,922,0,0)
  1295  #define	OP_EXTSW OPVCC(31,986,0,0)
  1296  #define	OP_MCRF	OPVCC(19,0,0,0)
  1297  #define	OP_MCRFS OPVCC(63,64,0,0)
  1298  #define	OP_MCRXR OPVCC(31,512,0,0)
  1299  #define	OP_MFCR	OPVCC(31,19,0,0)
  1300  #define	OP_MFFS	OPVCC(63,583,0,0)
  1301  #define	OP_MFMSR OPVCC(31,83,0,0)
  1302  #define	OP_MFSPR OPVCC(31,339,0,0)
  1303  #define	OP_MFSR	OPVCC(31,595,0,0)
  1304  #define	OP_MFSRIN	OPVCC(31,659,0,0)
  1305  #define	OP_MTCRF OPVCC(31,144,0,0)
  1306  #define	OP_MTFSF OPVCC(63,711,0,0)
  1307  #define	OP_MTFSFI OPVCC(63,134,0,0)
  1308  #define	OP_MTMSR OPVCC(31,146,0,0)
  1309  #define	OP_MTMSRD OPVCC(31,178,0,0)
  1310  #define	OP_MTSPR OPVCC(31,467,0,0)
  1311  #define	OP_MTSR	OPVCC(31,210,0,0)
  1312  #define	OP_MTSRIN	OPVCC(31,242,0,0)
  1313  #define	OP_MULLW OPVCC(31,235,0,0)
  1314  #define	OP_MULLD OPVCC(31,233,0,0)
  1315  #define	OP_OR	OPVCC(31,444,0,0)
  1316  #define	OP_ORI	OPVCC(24,0,0,0)
  1317  #define	OP_ORIS	OPVCC(25,0,0,0)
  1318  #define	OP_RLWINM	OPVCC(21,0,0,0)
  1319  #define	OP_SUBF	OPVCC(31,40,0,0)
  1320  #define	OP_RLDIC	OPVCC(30,4,0,0)
  1321  #define	OP_RLDICR	OPVCC(30,2,0,0)
  1322  #define	OP_RLDICL	OPVCC(30,0,0,0)
  1323  
  1324  #define	oclass(v)	((v).class-1)
  1325  
  1326  // add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
  1327  static void
  1328  addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2)
  1329  {
  1330  	Reloc *rel;
  1331  
  1332  	rel = addrel(ctxt->cursym);
  1333  	rel->off = ctxt->pc;
  1334  	rel->siz = 8;
  1335  	rel->sym = s;
  1336  	rel->add = ((uvlong)*o1<<32) | (uint32)*o2;
  1337  	rel->type = R_ADDRPOWER;
  1338  }
  1339  
  1340  /*
  1341   * 32-bit masks
  1342   */
  1343  static int
  1344  getmask(uchar *m, uint32 v)
  1345  {
  1346  	int i;
  1347  
  1348  	m[0] = m[1] = 0;
  1349  	if(v != ~0U && v & (1<<31) && v & 1){	/* MB > ME */
  1350  		if(getmask(m, ~v)){
  1351  			i = m[0]; m[0] = m[1]+1; m[1] = i-1;
  1352  			return 1;
  1353  		}
  1354  		return 0;
  1355  	}
  1356  	for(i=0; i<32; i++)
  1357  		if(v & (1<<(31-i))){
  1358  			m[0] = i;
  1359  			do {
  1360  				m[1] = i;
  1361  			} while(++i<32 && (v & (1<<(31-i))) != 0);
  1362  			for(; i<32; i++)
  1363  				if(v & (1<<(31-i)))
  1364  					return 0;
  1365  			return 1;
  1366  		}
  1367  	return 0;
  1368  }
  1369  
  1370  static void
  1371  maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v)
  1372  {
  1373  	if(!getmask(m, v))
  1374  		ctxt->diag("cannot generate mask #%lux\n%P", v, p);
  1375  }
  1376  
  1377  /*
  1378   * 64-bit masks (rldic etc)
  1379   */
  1380  static int
  1381  getmask64(uchar *m, uvlong v)
  1382  {
  1383  	int i;
  1384  
  1385  	m[0] = m[1] = 0;
  1386  	for(i=0; i<64; i++)
  1387  		if(v & ((uvlong)1<<(63-i))){
  1388  			m[0] = i;
  1389  			do {
  1390  				m[1] = i;
  1391  			} while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0);
  1392  			for(; i<64; i++)
  1393  				if(v & ((uvlong)1<<(63-i)))
  1394  					return 0;
  1395  			return 1;
  1396  		}
  1397  	return 0;
  1398  }
  1399  
  1400  static void
  1401  maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v)
  1402  {
  1403  	if(!getmask64(m, v))
  1404  		ctxt->diag("cannot generate mask #%llux\n%P", v, p);
  1405  }
  1406  
  1407  static uint32
  1408  loadu32(int r, vlong d)
  1409  {
  1410  	int32 v;
  1411  
  1412  	v = d>>16;
  1413  	if(isuint32(d))
  1414  		return LOP_IRR(OP_ORIS, r, REGZERO, v);
  1415  	return AOP_IRR(OP_ADDIS, r, REGZERO, v);
  1416  }
  1417  
  1418  static uint16
  1419  high16adjusted(int32 d)
  1420  {
  1421  	if(d & 0x8000)
  1422  		return (d>>16) + 1;
  1423  	return d>>16;
  1424  }
  1425  
  1426  static void
  1427  asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
  1428  {
  1429  	int32 o1, o2, o3, o4, o5, v, t;
  1430  	vlong d;
  1431  	int r, a;
  1432  	uchar mask[2];
  1433  	Reloc *rel;
  1434  
  1435  	o1 = 0;
  1436  	o2 = 0;
  1437  	o3 = 0;
  1438  	o4 = 0;
  1439  	o5 = 0;
  1440  
  1441  //print("%P => case %d\n", p, o->type);
  1442  	switch(o->type) {
  1443  	default:
  1444  		ctxt->diag("unknown type %d", o->type);
  1445  		prasm(p);
  1446  		break;
  1447  
  1448  	case 0:		/* pseudo ops */
  1449  		break;
  1450  
  1451  	case 1:		/* mov r1,r2 ==> OR Rs,Rs,Ra */
  1452  		if(p->to.reg == REGZERO && p->from.type == D_CONST) {
  1453  			v = regoff(ctxt, &p->from);
  1454  			if(r0iszero && v != 0) {
  1455  				//nerrors--;
  1456  				ctxt->diag("literal operation on R0\n%P", p);
  1457  			}
  1458  			o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
  1459  			break;
  1460  		}
  1461  		o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
  1462  		break;
  1463  
  1464  	case 2:		/* int/cr/fp op Rb,[Ra],Rd */
  1465  		r = p->reg;
  1466  		if(r == NREG)
  1467  			r = p->to.reg;
  1468  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1469  		break;
  1470  
  1471  	case 3:		/* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
  1472  		d = vregoff(ctxt, &p->from);
  1473  		v = d;
  1474  		r = p->from.reg;
  1475  		if(r == NREG)
  1476  			r = o->param;
  1477  		if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
  1478  			ctxt->diag("literal operation on R0\n%P", p);
  1479  		a = OP_ADDI;
  1480  		if(o->a1 == C_UCON) {
  1481  			if((d&0xffff) != 0)
  1482  				sysfatal("invalid handling of %P", p);
  1483  			v >>= 16;
  1484  			if(r == REGZERO && isuint32(d)){
  1485  				o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v);
  1486  				break;
  1487  			}
  1488  			a = OP_ADDIS;
  1489  		} else {
  1490  			if((int16)d != d)
  1491  				sysfatal("invalid handling of %P", p);
  1492  		}
  1493  		o1 = AOP_IRR(a, p->to.reg, r, v);
  1494  		break;
  1495  
  1496  	case 4:		/* add/mul $scon,[r1],r2 */
  1497  		v = regoff(ctxt, &p->from);
  1498  		r = p->reg;
  1499  		if(r == NREG)
  1500  			r = p->to.reg;
  1501  		if(r0iszero && p->to.reg == 0)
  1502  			ctxt->diag("literal operation on R0\n%P", p);
  1503  		if((int16)v != v)
  1504  			sysfatal("mishandled instruction %P", p);
  1505  		o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
  1506  		break;
  1507  
  1508  	case 5:		/* syscall */
  1509  		o1 = oprrr(ctxt, p->as);
  1510  		break;
  1511  
  1512  	case 6:		/* logical op Rb,[Rs,]Ra; no literal */
  1513  		r = p->reg;
  1514  		if(r == NREG)
  1515  			r = p->to.reg;
  1516  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1517  		break;
  1518  
  1519  	case 7:		/* mov r, soreg ==> stw o(r) */
  1520  		r = p->to.reg;
  1521  		if(r == NREG)
  1522  			r = o->param;
  1523  		v = regoff(ctxt, &p->to);
  1524  		if(p->to.type == D_OREG && p->reg != NREG) {
  1525  			if(v)
  1526  				ctxt->diag("illegal indexed instruction\n%P", p);
  1527  			o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r);
  1528  		} else {
  1529  			if((int16)v != v)
  1530  				sysfatal("mishandled instruction %P", p);	
  1531  			o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v);
  1532  		}
  1533  		break;
  1534  
  1535  	case 8:		/* mov soreg, r ==> lbz/lhz/lwz o(r) */
  1536  		r = p->from.reg;
  1537  		if(r == NREG)
  1538  			r = o->param;
  1539  		v = regoff(ctxt, &p->from);
  1540  		if(p->from.type == D_OREG && p->reg != NREG) {
  1541  			if(v)
  1542  				ctxt->diag("illegal indexed instruction\n%P", p);
  1543  			o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
  1544  		} else {
  1545  			if((int16)v != v)
  1546  				sysfatal("mishandled instruction %P", p);
  1547  			o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
  1548  		}
  1549  		break;
  1550  
  1551  	case 9:		/* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
  1552  		r = p->from.reg;
  1553  		if(r == NREG)
  1554  			r = o->param;
  1555  		v = regoff(ctxt, &p->from);
  1556  		if(p->from.type == D_OREG && p->reg != NREG) {
  1557  			if(v)
  1558  				ctxt->diag("illegal indexed instruction\n%P", p);
  1559  			o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
  1560  		} else
  1561  			o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
  1562  		o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  1563  		break;
  1564  
  1565  	case 10:		/* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
  1566  		r = p->reg;
  1567  		if(r == NREG)
  1568  			r = p->to.reg;
  1569  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r);
  1570  		break;
  1571  
  1572  	case 11:	/* br/bl lbra */
  1573  		v = 0;
  1574  		if(p->pcond) {
  1575  			v = p->pcond->pc - p->pc;
  1576  			if(v & 03) {
  1577  				ctxt->diag("odd branch target address\n%P", p);
  1578  				v &= ~03;
  1579  			}
  1580  			if(v < -(1L<<25) || v >= (1L<<24))
  1581  				ctxt->diag("branch too far\n%P", p);
  1582  		}
  1583  		o1 = OP_BR(opirr(ctxt, p->as), v, 0);
  1584  		if(p->to.sym != nil) {
  1585  			rel = addrel(ctxt->cursym);
  1586  			rel->off = ctxt->pc;
  1587  			rel->siz = 4;
  1588  			rel->sym = p->to.sym;
  1589  			v += p->to.offset;
  1590  			if(v & 03) {
  1591  				ctxt->diag("odd branch target address\n%P", p);
  1592  				v &= ~03;
  1593  			}
  1594  			rel->add = v;
  1595  			rel->type = R_CALLPOWER;
  1596  		}
  1597  		break;
  1598  
  1599  	case 12:	/* movb r,r (extsb); movw r,r (extsw) */
  1600  		if(p->to.reg == REGZERO && p->from.type == D_CONST) {
  1601  			v = regoff(ctxt, &p->from);
  1602  			if(r0iszero && v != 0) {
  1603  				ctxt->diag("literal operation on R0\n%P", p);
  1604  			}
  1605  			o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
  1606  			break;
  1607  		}
  1608  		if(p->as == AMOVW)
  1609  			o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0);
  1610  		else
  1611  			o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
  1612  		break;
  1613  
  1614  	case 13:	/* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
  1615  		if(p->as == AMOVBZ)
  1616  			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
  1617  		else if(p->as == AMOVH)
  1618  			o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
  1619  		else if(p->as == AMOVHZ)
  1620  			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
  1621  		else if(p->as == AMOVWZ)
  1622  			o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5);	/* MB=32 */
  1623  		else
  1624  			ctxt->diag("internal: bad mov[bhw]z\n%P", p);
  1625  		break;
  1626  
  1627  	case 14:	/* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
  1628  		r = p->reg;
  1629  		if(r == NREG)
  1630  			r = p->to.reg;
  1631  		d = vregoff(ctxt, &p->from3);
  1632  		maskgen64(ctxt, p, mask, d);
  1633  		switch(p->as){
  1634  		case ARLDCL: case ARLDCLCC:
  1635  			a = mask[0];	/* MB */
  1636  			if(mask[1] != 63)
  1637  				ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p);
  1638  			break;
  1639  		case ARLDCR: case ARLDCRCC:
  1640  			a = mask[1];	/* ME */
  1641  			if(mask[0] != 0)
  1642  				ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p);
  1643  			break;
  1644  		default:
  1645  			ctxt->diag("unexpected op in rldc case\n%P", p);
  1646  			a = 0;
  1647  		}
  1648  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
  1649  		o1 |= (a&31L)<<6;
  1650  		if(a & 0x20)
  1651  			o1 |= 1<<5;	/* mb[5] is top bit */
  1652  		break;
  1653  
  1654  	case 17:	/* bc bo,bi,lbra (same for now) */
  1655  	case 16:	/* bc bo,bi,sbra */
  1656  		a = 0;
  1657  		if(p->from.type == D_CONST)
  1658  			a = regoff(ctxt, &p->from);
  1659  		r = p->reg;
  1660  		if(r == NREG)
  1661  			r = 0;
  1662  		v = 0;
  1663  		if(p->pcond)
  1664  			v = p->pcond->pc - p->pc;
  1665  		if(v & 03) {
  1666  			ctxt->diag("odd branch target address\n%P", p);
  1667  			v &= ~03;
  1668  		}
  1669  		if(v < -(1L<<16) || v >= (1L<<15))
  1670  			ctxt->diag("branch too far\n%P", p);
  1671  		o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0);
  1672  		break;
  1673  
  1674  	case 15:	/* br/bl (r) => mov r,lr; br/bl (lr) */
  1675  		if(p->as == ABC || p->as == ABCL)
  1676  			v = regoff(ctxt, &p->to)&31L;
  1677  		else
  1678  			v = 20;	/* unconditional */
  1679  		r = p->reg;
  1680  		if(r == NREG)
  1681  			r = 0;
  1682  		o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
  1683  		o2 = OPVCC(19, 16, 0, 0);
  1684  		if(p->as == ABL || p->as == ABCL)
  1685  			o2 |= 1;
  1686  		o2 = OP_BCR(o2, v, r);
  1687  		break;
  1688  
  1689  	case 18:	/* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
  1690  		if(p->as == ABC || p->as == ABCL)
  1691  			v = regoff(ctxt, &p->from)&31L;
  1692  		else
  1693  			v = 20;	/* unconditional */
  1694  		r = p->reg;
  1695  		if(r == NREG)
  1696  			r = 0;
  1697  		switch(oclass(p->to)) {
  1698  		case C_CTR:
  1699  			o1 = OPVCC(19, 528, 0, 0);
  1700  			break;
  1701  		case C_LR:
  1702  			o1 = OPVCC(19, 16, 0, 0);
  1703  			break;
  1704  		default:
  1705  			ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p);
  1706  			v = 0;
  1707  		}
  1708  		if(p->as == ABL || p->as == ABCL)
  1709  			o1 |= 1;
  1710  		o1 = OP_BCR(o1, v, r);
  1711  		break;
  1712  
  1713  	case 19:	/* mov $lcon,r ==> cau+or */
  1714  		d = vregoff(ctxt, &p->from);
  1715  		if(p->from.sym == nil) {
  1716  			o1 = loadu32(p->to.reg, d);
  1717  			o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d);
  1718  		} else {
  1719  			o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d));
  1720  			o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d);
  1721  			addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  1722  		}
  1723  		//if(dlm) reloc(&p->from, p->pc, 0);
  1724  		break;
  1725  
  1726  	case 20:	/* add $ucon,,r */
  1727  		v = regoff(ctxt, &p->from);
  1728  		r = p->reg;
  1729  		if(r == NREG)
  1730  			r = p->to.reg;
  1731  		if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
  1732  			ctxt->diag("literal operation on R0\n%P", p);
  1733  		o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);
  1734  		break;
  1735  
  1736  	case 22:	/* add $lcon,r1,r2 ==> cau+or+add */	/* could do add/sub more efficiently */
  1737  		if(p->to.reg == REGTMP || p->reg == REGTMP)
  1738  			ctxt->diag("cant synthesize large constant\n%P", p);
  1739  		d = vregoff(ctxt, &p->from);
  1740  		o1 = loadu32(REGTMP, d);
  1741  		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
  1742  		r = p->reg;
  1743  		if(r == NREG)
  1744  			r = p->to.reg;
  1745  		o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
  1746  		if(p->from.sym != nil)
  1747  			ctxt->diag("%P is not supported", p);
  1748  		//if(dlm) reloc(&p->from, p->pc, 0);
  1749  		break;
  1750  
  1751  	case 23:	/* and $lcon,r1,r2 ==> cau+or+and */	/* masks could be done using rlnm etc. */
  1752  		if(p->to.reg == REGTMP || p->reg == REGTMP)
  1753  			ctxt->diag("cant synthesize large constant\n%P", p);
  1754  		d = vregoff(ctxt, &p->from);
  1755  		o1 = loadu32(REGTMP, d);
  1756  		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
  1757  		r = p->reg;
  1758  		if(r == NREG)
  1759  			r = p->to.reg;
  1760  		o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
  1761  		if(p->from.sym != nil)
  1762  			ctxt->diag("%P is not supported", p);
  1763  		//if(dlm) reloc(&p->from, p->pc, 0);
  1764  		break;
  1765  /*24*/
  1766  
  1767  	case 25:	/* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
  1768  		v = regoff(ctxt, &p->from);
  1769  		if(v < 0)
  1770  			v = 0;
  1771  		else if(v > 63)
  1772  			v = 63;
  1773  		r = p->reg;
  1774  		if(r == NREG)
  1775  			r = p->to.reg;
  1776  		switch(p->as){
  1777  		case ASLD: case ASLDCC:
  1778  			a = 63-v;
  1779  			o1 = OP_RLDICR;
  1780  			break;
  1781  		case ASRD: case ASRDCC:
  1782  			a = v;
  1783  			v = 64-v;
  1784  			o1 = OP_RLDICL;
  1785  			break;
  1786  		default:
  1787  			ctxt->diag("unexpected op in sldi case\n%P", p);
  1788  			a = 0;
  1789  			o1 = 0;
  1790  		}
  1791  		o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F));
  1792  		o1 |= (a&31L)<<6;
  1793  		if(v & 0x20)
  1794  			o1 |= 1<<1;
  1795  		if(a & 0x20)
  1796  			o1 |= 1<<5;	/* mb[5] is top bit */
  1797  		if(p->as == ASLDCC || p->as == ASRDCC)
  1798  			o1 |= 1;	/* Rc */
  1799  		break;
  1800  
  1801  	case 26:	/* mov $lsext/auto/oreg,,r2 ==> addis+addi */
  1802  		if(p->to.reg == REGTMP)
  1803  			ctxt->diag("can't synthesize large constant\n%P", p);
  1804  		v = regoff(ctxt, &p->from);
  1805  		r = p->from.reg;
  1806  		if(r == NREG)
  1807  			r = o->param;
  1808  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
  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  		r = p->to.reg;
  1917  		if(r == NREG)
  1918  			r = o->param;
  1919  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
  1920  		o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
  1921  		break;
  1922  
  1923  	case 36:	/* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
  1924  		v = regoff(ctxt, &p->from);
  1925  		r = p->from.reg;
  1926  		if(r == NREG)
  1927  			r = o->param;
  1928  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
  1929  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  1930  		break;
  1931  
  1932  	case 37:	/* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
  1933  		v = regoff(ctxt, &p->from);
  1934  		r = p->from.reg;
  1935  		if(r == NREG)
  1936  			r = o->param;
  1937  		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
  1938  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  1939  		o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  1940  		break;
  1941  
  1942  	case 40:	/* word */
  1943  		o1 = regoff(ctxt, &p->from);
  1944  		break;
  1945  
  1946  	case 41:	/* stswi */
  1947  		o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
  1948  		break;
  1949  
  1950  	case 42:	/* lswi */
  1951  		o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
  1952  		break;
  1953  
  1954  	case 43:	/* unary indexed source: dcbf (b); dcbf (a+b) */
  1955  		r = p->reg;
  1956  		if(r == NREG)
  1957  			r = 0;
  1958  		o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg);
  1959  		break;
  1960  
  1961  	case 44:	/* indexed store */
  1962  		r = p->reg;
  1963  		if(r == NREG)
  1964  			r = 0;
  1965  		o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg);
  1966  		break;
  1967  	case 45:	/* indexed load */
  1968  		r = p->reg;
  1969  		if(r == NREG)
  1970  			r = 0;
  1971  		o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg);
  1972  		break;
  1973  
  1974  	case 46:	/* plain op */
  1975  		o1 = oprrr(ctxt, p->as);
  1976  		break;
  1977  
  1978  	case 47:	/* op Ra, Rd; also op [Ra,] Rd */
  1979  		r = p->from.reg;
  1980  		if(r == NREG)
  1981  			r = p->to.reg;
  1982  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
  1983  		break;
  1984  
  1985  	case 48:	/* op Rs, Ra */
  1986  		r = p->from.reg;
  1987  		if(r == NREG)
  1988  			r = p->to.reg;
  1989  		o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
  1990  		break;
  1991  
  1992  	case 49:	/* op Rb; op $n, Rb */
  1993  		if(p->from.type != D_REG){	/* tlbie $L, rB */
  1994  			v = regoff(ctxt, &p->from) & 1;
  1995  			o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21);
  1996  		}else
  1997  			o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg);
  1998  		break;
  1999  
  2000  	case 50:	/* rem[u] r1[,r2],r3 */
  2001  		r = p->reg;
  2002  		if(r == NREG)
  2003  			r = p->to.reg;
  2004  		v = oprrr(ctxt, p->as);
  2005  		t = v & ((1<<10)|1);	/* OE|Rc */
  2006  		o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
  2007  		o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
  2008  		o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
  2009  		if(p->as == AREMU) {
  2010  			o4 = o3;
  2011  			/* Clear top 32 bits */
  2012  			o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5);
  2013  		}
  2014  		break;
  2015  
  2016  	case 51:	/* remd[u] r1[,r2],r3 */
  2017  		r = p->reg;
  2018  		if(r == NREG)
  2019  			r = p->to.reg;
  2020  		v = oprrr(ctxt, p->as);
  2021  		t = v & ((1<<10)|1);	/* OE|Rc */
  2022  		o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
  2023  		o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg);
  2024  		o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
  2025  		break;
  2026  
  2027  	case 52:	/* mtfsbNx cr(n) */
  2028  		v = regoff(ctxt, &p->from)&31L;
  2029  		o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0);
  2030  		break;
  2031  
  2032  	case 53:	/* mffsX ,fr1 */
  2033  		o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
  2034  		break;
  2035  
  2036  	case 54:	/* mov msr,r1; mov r1, msr*/
  2037  		if(oclass(p->from) == C_REG){
  2038  			if(p->as == AMOVD)
  2039  				o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0);
  2040  			else
  2041  				o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
  2042  		}else
  2043  			o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
  2044  		break;
  2045  
  2046  	case 55:	/* op Rb, Rd */
  2047  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg);
  2048  		break;
  2049  
  2050  	case 56:	/* sra $sh,[s,]a; srd $sh,[s,]a */
  2051  		v = regoff(ctxt, &p->from);
  2052  		r = p->reg;
  2053  		if(r == NREG)
  2054  			r = p->to.reg;
  2055  		o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L);
  2056  		if(p->as == ASRAD && (v&0x20))
  2057  			o1 |= 1<<1;	/* mb[5] */
  2058  		break;
  2059  
  2060  	case 57:	/* slw $sh,[s,]a -> rlwinm ... */
  2061  		v = regoff(ctxt, &p->from);
  2062  		r = p->reg;
  2063  		if(r == NREG)
  2064  			r = p->to.reg;
  2065  		/*
  2066  		 * Let user (gs) shoot himself in the foot. 
  2067  		 * qc has already complained.
  2068  		 *
  2069  		if(v < 0 || v > 31)
  2070  			ctxt->diag("illegal shift %ld\n%P", v, p);
  2071  		 */
  2072  		if(v < 0)
  2073  			v = 0;
  2074  		else if(v > 32)
  2075  			v = 32;
  2076  		if(p->as == ASRW || p->as == ASRWCC) {	/* shift right */
  2077  			mask[0] = v;
  2078  			mask[1] = 31;
  2079  			v = 32-v;
  2080  		} else {
  2081  			mask[0] = 0;
  2082  			mask[1] = 31-v;
  2083  		}
  2084  		o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
  2085  		if(p->as == ASLWCC || p->as == ASRWCC)
  2086  			o1 |= 1;	/* Rc */
  2087  		break;
  2088  
  2089  	case 58:		/* logical $andcon,[s],a */
  2090  		v = regoff(ctxt, &p->from);
  2091  		r = p->reg;
  2092  		if(r == NREG)
  2093  			r = p->to.reg;
  2094  		o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
  2095  		break;
  2096  
  2097  	case 59:	/* or/and $ucon,,r */
  2098  		v = regoff(ctxt, &p->from);
  2099  		r = p->reg;
  2100  		if(r == NREG)
  2101  			r = p->to.reg;
  2102  		o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);	/* oris, xoris, andis */
  2103  		break;
  2104  
  2105  	case 60:	/* tw to,a,b */
  2106  		r = regoff(ctxt, &p->from)&31L;
  2107  		o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg);
  2108  		break;
  2109  
  2110  	case 61:	/* tw to,a,$simm */
  2111  		r = regoff(ctxt, &p->from)&31L;
  2112  		v = regoff(ctxt, &p->to);
  2113  		o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v);
  2114  		break;
  2115  
  2116  	case 62:	/* rlwmi $sh,s,$mask,a */
  2117  		v = regoff(ctxt, &p->from);
  2118  		maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
  2119  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v);
  2120  		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  2121  		break;
  2122  
  2123  	case 63:	/* rlwmi b,s,$mask,a */
  2124  		maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
  2125  		o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg);
  2126  		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  2127  		break;
  2128  
  2129  	case 64:	/* mtfsf fr[, $m] {,fpcsr} */
  2130  		if(p->from3.type != D_NONE)
  2131  			v = regoff(ctxt, &p->from3)&255L;
  2132  		else
  2133  			v = 255;
  2134  		o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
  2135  		break;
  2136  
  2137  	case 65:	/* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
  2138  		if(p->to.reg == NREG)
  2139  			ctxt->diag("must specify FPSCR(n)\n%P", p);
  2140  		o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12);
  2141  		break;
  2142  
  2143  	case 66:	/* mov spr,r1; mov r1,spr, also dcr */
  2144  		if(p->from.type == D_REG) {
  2145  			r = p->from.reg;
  2146  			v = p->to.offset;
  2147  			if(p->to.type == D_DCR)
  2148  				o1 = OPVCC(31,451,0,0);	/* mtdcr */
  2149  			else
  2150  				o1 = OPVCC(31,467,0,0); /* mtspr */
  2151  		} else {
  2152  			r = p->to.reg;
  2153  			v = p->from.offset;
  2154  			if(p->from.type == D_DCR)
  2155  				o1 = OPVCC(31,323,0,0);	/* mfdcr */
  2156  			else
  2157  				o1 = OPVCC(31,339,0,0);	/* mfspr */
  2158  		}
  2159  		o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
  2160  		break;
  2161  
  2162  	case 67:	/* mcrf crfD,crfS */
  2163  		if(p->from.type != D_CREG || p->from.reg == NREG ||
  2164  		   p->to.type != D_CREG || p->to.reg == NREG)
  2165  			ctxt->diag("illegal CR field number\n%P", p);
  2166  		o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  2167  		break;
  2168  
  2169  	case 68:	/* mfcr rD; mfocrf CRM,rD */
  2170  		if(p->from.type == D_CREG && p->from.reg != NREG){
  2171  			v = 1<<(7-(p->to.reg&7));	/* CR(n) */
  2172  			o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12);	/* new form, mfocrf */
  2173  		}else
  2174  			o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0);	/* old form, whole register */
  2175  		break;
  2176  
  2177  	case 69:	/* mtcrf CRM,rS */
  2178  		if(p->from3.type != D_NONE) {
  2179  			if(p->to.reg != NREG)
  2180  				ctxt->diag("can't use both mask and CR(n)\n%P", p);
  2181  			v = regoff(ctxt, &p->from3) & 0xff;
  2182  		} else {
  2183  			if(p->to.reg == NREG)
  2184  				v = 0xff;	/* CR */
  2185  			else
  2186  				v = 1<<(7-(p->to.reg&7));	/* CR(n) */
  2187  		}
  2188  		o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
  2189  		break;
  2190  
  2191  	case 70:	/* [f]cmp r,r,cr*/
  2192  		if(p->reg == NREG)
  2193  			r = 0;
  2194  		else
  2195  			r = (p->reg&7)<<2;
  2196  		o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg);
  2197  		break;
  2198  
  2199  	case 71:	/* cmp[l] r,i,cr*/
  2200  		if(p->reg == NREG)
  2201  			r = 0;
  2202  		else
  2203  			r = (p->reg&7)<<2;
  2204  		o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff);
  2205  		break;
  2206  
  2207  	case 72:	/* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
  2208  		o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg);
  2209  		break;
  2210  
  2211  	case 73:	/* mcrfs crfD,crfS */
  2212  		if(p->from.type != D_FPSCR || p->from.reg == NREG ||
  2213  		   p->to.type != D_CREG || p->to.reg == NREG)
  2214  			ctxt->diag("illegal FPSCR/CR field number\n%P", p);
  2215  		o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  2216  		break;
  2217  
  2218  	case 77:	/* syscall $scon, syscall Rx */
  2219  		if(p->from.type == D_CONST) {
  2220  			if(p->from.offset > BIG || p->from.offset < -BIG)
  2221  				ctxt->diag("illegal syscall, sysnum too large: %P", p);
  2222  			o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset);
  2223  		} else if(p->from.type == D_REG) {
  2224  			o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg);
  2225  		} else {
  2226  			ctxt->diag("illegal syscall: %P", p);
  2227  			o1 = 0x7fe00008; // trap always
  2228  		}
  2229  		o2 = oprrr(ctxt, p->as);
  2230  		o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0
  2231  		break;
  2232  
  2233  	case 78:	/* undef */
  2234  		o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed
  2235  			   always to be an illegal instruction."  */
  2236  		break;
  2237  
  2238  	/* relocation operations */
  2239  
  2240  	case 74:
  2241  		v = regoff(ctxt, &p->to);
  2242  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2243  		o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
  2244  		addaddrreloc(ctxt, p->to.sym, &o1, &o2);
  2245  		//if(dlm) reloc(&p->to, p->pc, 1);
  2246  		break;
  2247  
  2248  	case 75:
  2249  		v = regoff(ctxt, &p->from);
  2250  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2251  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  2252  		addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  2253  		//if(dlm) reloc(&p->from, p->pc, 1);
  2254  		break;
  2255  
  2256  	case 76:
  2257  		v = regoff(ctxt, &p->from);
  2258  		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
  2259  		o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
  2260  		addaddrreloc(ctxt, p->from.sym, &o1, &o2);
  2261  		o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  2262  		//if(dlm) reloc(&p->from, p->pc, 1);
  2263  		break;
  2264  
  2265  	}
  2266  
  2267  	out[0] = o1;
  2268  	out[1] = o2;
  2269  	out[2] = o3;
  2270  	out[3] = o4;
  2271  	out[4] = o5;
  2272  	return;
  2273  }
  2274  
  2275  static vlong
  2276  vregoff(Link *ctxt, Addr *a)
  2277  {
  2278  
  2279  	ctxt->instoffset = 0;
  2280  	aclass(ctxt, a);
  2281  	return ctxt->instoffset;
  2282  }
  2283  
  2284  static int32
  2285  regoff(Link *ctxt, Addr *a)
  2286  {
  2287  	return vregoff(ctxt, a);
  2288  }
  2289  
  2290  static int32
  2291  oprrr(Link *ctxt, int a)
  2292  {
  2293  	switch(a) {
  2294  	case AADD:	return OPVCC(31,266,0,0);
  2295  	case AADDCC:	return OPVCC(31,266,0,1);
  2296  	case AADDV:	return OPVCC(31,266,1,0);
  2297  	case AADDVCC:	return OPVCC(31,266,1,1);
  2298  	case AADDC:	return OPVCC(31,10,0,0);
  2299  	case AADDCCC:	return OPVCC(31,10,0,1);
  2300  	case AADDCV:	return OPVCC(31,10,1,0);
  2301  	case AADDCVCC:	return OPVCC(31,10,1,1);
  2302  	case AADDE:	return OPVCC(31,138,0,0);
  2303  	case AADDECC:	return OPVCC(31,138,0,1);
  2304  	case AADDEV:	return OPVCC(31,138,1,0);
  2305  	case AADDEVCC:	return OPVCC(31,138,1,1);
  2306  	case AADDME:	return OPVCC(31,234,0,0);
  2307  	case AADDMECC:	return OPVCC(31,234,0,1);
  2308  	case AADDMEV:	return OPVCC(31,234,1,0);
  2309  	case AADDMEVCC:	return OPVCC(31,234,1,1);
  2310  	case AADDZE:	return OPVCC(31,202,0,0);
  2311  	case AADDZECC:	return OPVCC(31,202,0,1);
  2312  	case AADDZEV:	return OPVCC(31,202,1,0);
  2313  	case AADDZEVCC:	return OPVCC(31,202,1,1);
  2314  
  2315  	case AAND:	return OPVCC(31,28,0,0);
  2316  	case AANDCC:	return OPVCC(31,28,0,1);
  2317  	case AANDN:	return OPVCC(31,60,0,0);
  2318  	case AANDNCC:	return OPVCC(31,60,0,1);
  2319  
  2320  	case ACMP:	return OPVCC(31,0,0,0)|(1<<21);	/* L=1 */
  2321  	case ACMPU:	return OPVCC(31,32,0,0)|(1<<21);
  2322  	case ACMPW:	return OPVCC(31,0,0,0);	/* L=0 */
  2323  	case ACMPWU:	return OPVCC(31,32,0,0);
  2324  
  2325  	case ACNTLZW:	return OPVCC(31,26,0,0);
  2326  	case ACNTLZWCC:	return OPVCC(31,26,0,1);
  2327  	case ACNTLZD:		return OPVCC(31,58,0,0);
  2328  	case ACNTLZDCC:	return OPVCC(31,58,0,1);
  2329  
  2330  	case ACRAND:	return OPVCC(19,257,0,0);
  2331  	case ACRANDN:	return OPVCC(19,129,0,0);
  2332  	case ACREQV:	return OPVCC(19,289,0,0);
  2333  	case ACRNAND:	return OPVCC(19,225,0,0);
  2334  	case ACRNOR:	return OPVCC(19,33,0,0);
  2335  	case ACROR:	return OPVCC(19,449,0,0);
  2336  	case ACRORN:	return OPVCC(19,417,0,0);
  2337  	case ACRXOR:	return OPVCC(19,193,0,0);
  2338  
  2339  	case ADCBF:	return OPVCC(31,86,0,0);
  2340  	case ADCBI:	return OPVCC(31,470,0,0);
  2341  	case ADCBST:	return OPVCC(31,54,0,0);
  2342  	case ADCBT:	return OPVCC(31,278,0,0);
  2343  	case ADCBTST:	return OPVCC(31,246,0,0);
  2344  	case ADCBZ:	return OPVCC(31,1014,0,0);
  2345  
  2346  	case AREM:
  2347  	case ADIVW:	return OPVCC(31,491,0,0);
  2348  	case AREMCC:
  2349  	case ADIVWCC:	return OPVCC(31,491,0,1);
  2350  	case AREMV:
  2351  	case ADIVWV:	return OPVCC(31,491,1,0);
  2352  	case AREMVCC:
  2353  	case ADIVWVCC:	return OPVCC(31,491,1,1);
  2354  	case AREMU:
  2355  	case ADIVWU:	return OPVCC(31,459,0,0);
  2356  	case AREMUCC:
  2357  	case ADIVWUCC:	return OPVCC(31,459,0,1);
  2358  	case AREMUV:
  2359  	case ADIVWUV:	return OPVCC(31,459,1,0);
  2360  	case AREMUVCC:
  2361  	case ADIVWUVCC:	return OPVCC(31,459,1,1);
  2362  
  2363  	case AREMD:
  2364  	case ADIVD:	return OPVCC(31,489,0,0);
  2365  	case AREMDCC:
  2366  	case ADIVDCC:	return OPVCC(31,489,0,1);
  2367  	case AREMDV:
  2368  	case ADIVDV:	return OPVCC(31,489,1,0);
  2369  	case AREMDVCC:
  2370  	case ADIVDVCC:	return OPVCC(31,489,1,1);
  2371  	case AREMDU:
  2372  	case ADIVDU:	return OPVCC(31,457,0,0);
  2373  	case AREMDUCC:
  2374  	case ADIVDUCC:	return OPVCC(31,457,0,1);
  2375  	case AREMDUV:
  2376  	case ADIVDUV:	return OPVCC(31,457,1,0);
  2377  	case AREMDUVCC:
  2378  	case ADIVDUVCC:	return OPVCC(31,457,1,1);
  2379  
  2380  	case AEIEIO:	return OPVCC(31,854,0,0);
  2381  
  2382  	case AEQV:	return OPVCC(31,284,0,0);
  2383  	case AEQVCC:	return OPVCC(31,284,0,1);
  2384  
  2385  	case AEXTSB:	return OPVCC(31,954,0,0);
  2386  	case AEXTSBCC:	return OPVCC(31,954,0,1);
  2387  	case AEXTSH:	return OPVCC(31,922,0,0);
  2388  	case AEXTSHCC:	return OPVCC(31,922,0,1);
  2389  	case AEXTSW:	return OPVCC(31,986,0,0);
  2390  	case AEXTSWCC:	return OPVCC(31,986,0,1);
  2391  
  2392  	case AFABS:	return OPVCC(63,264,0,0);
  2393  	case AFABSCC:	return OPVCC(63,264,0,1);
  2394  	case AFADD:	return OPVCC(63,21,0,0);
  2395  	case AFADDCC:	return OPVCC(63,21,0,1);
  2396  	case AFADDS:	return OPVCC(59,21,0,0);
  2397  	case AFADDSCC:	return OPVCC(59,21,0,1);
  2398  	case AFCMPO:	return OPVCC(63,32,0,0);
  2399  	case AFCMPU:	return OPVCC(63,0,0,0);
  2400  	case AFCFID:	return OPVCC(63,846,0,0);
  2401  	case AFCFIDCC:	return OPVCC(63,846,0,1);
  2402  	case AFCTIW:	return OPVCC(63,14,0,0);
  2403  	case AFCTIWCC:	return OPVCC(63,14,0,1);
  2404  	case AFCTIWZ:	return OPVCC(63,15,0,0);
  2405  	case AFCTIWZCC:	return OPVCC(63,15,0,1);
  2406  	case AFCTID:	return OPVCC(63,814,0,0);
  2407  	case AFCTIDCC:	return OPVCC(63,814,0,1);
  2408  	case AFCTIDZ:	return OPVCC(63,815,0,0);
  2409  	case AFCTIDZCC:	return OPVCC(63,815,0,1);
  2410  	case AFDIV:	return OPVCC(63,18,0,0);
  2411  	case AFDIVCC:	return OPVCC(63,18,0,1);
  2412  	case AFDIVS:	return OPVCC(59,18,0,0);
  2413  	case AFDIVSCC:	return OPVCC(59,18,0,1);
  2414  	case AFMADD:	return OPVCC(63,29,0,0);
  2415  	case AFMADDCC:	return OPVCC(63,29,0,1);
  2416  	case AFMADDS:	return OPVCC(59,29,0,0);
  2417  	case AFMADDSCC:	return OPVCC(59,29,0,1);
  2418  	case AFMOVS:
  2419  	case AFMOVD:	return OPVCC(63,72,0,0);	/* load */
  2420  	case AFMOVDCC:	return OPVCC(63,72,0,1);
  2421  	case AFMSUB:	return OPVCC(63,28,0,0);
  2422  	case AFMSUBCC:	return OPVCC(63,28,0,1);
  2423  	case AFMSUBS:	return OPVCC(59,28,0,0);
  2424  	case AFMSUBSCC:	return OPVCC(59,28,0,1);
  2425  	case AFMUL:	return OPVCC(63,25,0,0);
  2426  	case AFMULCC:	return OPVCC(63,25,0,1);
  2427  	case AFMULS:	return OPVCC(59,25,0,0);
  2428  	case AFMULSCC:	return OPVCC(59,25,0,1);
  2429  	case AFNABS:	return OPVCC(63,136,0,0);
  2430  	case AFNABSCC:	return OPVCC(63,136,0,1);
  2431  	case AFNEG:	return OPVCC(63,40,0,0);
  2432  	case AFNEGCC:	return OPVCC(63,40,0,1);
  2433  	case AFNMADD:	return OPVCC(63,31,0,0);
  2434  	case AFNMADDCC:	return OPVCC(63,31,0,1);
  2435  	case AFNMADDS:	return OPVCC(59,31,0,0);
  2436  	case AFNMADDSCC:	return OPVCC(59,31,0,1);
  2437  	case AFNMSUB:	return OPVCC(63,30,0,0);
  2438  	case AFNMSUBCC:	return OPVCC(63,30,0,1);
  2439  	case AFNMSUBS:	return OPVCC(59,30,0,0);
  2440  	case AFNMSUBSCC:	return OPVCC(59,30,0,1);
  2441  	case AFRES:	return OPVCC(59,24,0,0);
  2442  	case AFRESCC:	return OPVCC(59,24,0,1);
  2443  	case AFRSP:	return OPVCC(63,12,0,0);
  2444  	case AFRSPCC:	return OPVCC(63,12,0,1);
  2445  	case AFRSQRTE:	return OPVCC(63,26,0,0);
  2446  	case AFRSQRTECC:	return OPVCC(63,26,0,1);
  2447  	case AFSEL:	return OPVCC(63,23,0,0);
  2448  	case AFSELCC:	return OPVCC(63,23,0,1);
  2449  	case AFSQRT:	return OPVCC(63,22,0,0);
  2450  	case AFSQRTCC:	return OPVCC(63,22,0,1);
  2451  	case AFSQRTS:	return OPVCC(59,22,0,0);
  2452  	case AFSQRTSCC:	return OPVCC(59,22,0,1);
  2453  	case AFSUB:	return OPVCC(63,20,0,0);
  2454  	case AFSUBCC:	return OPVCC(63,20,0,1);
  2455  	case AFSUBS:	return OPVCC(59,20,0,0);
  2456  	case AFSUBSCC:	return OPVCC(59,20,0,1);
  2457  
  2458  	case AICBI:	return OPVCC(31,982,0,0);
  2459  	case AISYNC:	return OPVCC(19,150,0,0);
  2460  
  2461  	case AMTFSB0:	return OPVCC(63,70,0,0);
  2462  	case AMTFSB0CC:	return OPVCC(63,70,0,1);
  2463  	case AMTFSB1:	return OPVCC(63,38,0,0);
  2464  	case AMTFSB1CC:	return OPVCC(63,38,0,1);
  2465  
  2466  	case AMULHW:	return OPVCC(31,75,0,0);
  2467  	case AMULHWCC:	return OPVCC(31,75,0,1);
  2468  	case AMULHWU:	return OPVCC(31,11,0,0);
  2469  	case AMULHWUCC:	return OPVCC(31,11,0,1);
  2470  	case AMULLW:	return OPVCC(31,235,0,0);
  2471  	case AMULLWCC:	return OPVCC(31,235,0,1);
  2472  	case AMULLWV:	return OPVCC(31,235,1,0);
  2473  	case AMULLWVCC:	return OPVCC(31,235,1,1);
  2474  
  2475  	case AMULHD:	return OPVCC(31,73,0,0);
  2476  	case AMULHDCC:	return OPVCC(31,73,0,1);
  2477  	case AMULHDU:	return OPVCC(31,9,0,0);
  2478  	case AMULHDUCC:	return OPVCC(31,9,0,1);
  2479  	case AMULLD:	return OPVCC(31,233,0,0);
  2480  	case AMULLDCC:	return OPVCC(31,233,0,1);
  2481  	case AMULLDV:	return OPVCC(31,233,1,0);
  2482  	case AMULLDVCC:	return OPVCC(31,233,1,1);
  2483  
  2484  	case ANAND:	return OPVCC(31,476,0,0);
  2485  	case ANANDCC:	return OPVCC(31,476,0,1);
  2486  	case ANEG:	return OPVCC(31,104,0,0);
  2487  	case ANEGCC:	return OPVCC(31,104,0,1);
  2488  	case ANEGV:	return OPVCC(31,104,1,0);
  2489  	case ANEGVCC:	return OPVCC(31,104,1,1);
  2490  	case ANOR:	return OPVCC(31,124,0,0);
  2491  	case ANORCC:	return OPVCC(31,124,0,1);
  2492  	case AOR:	return OPVCC(31,444,0,0);
  2493  	case AORCC:	return OPVCC(31,444,0,1);
  2494  	case AORN:	return OPVCC(31,412,0,0);
  2495  	case AORNCC:	return OPVCC(31,412,0,1);
  2496  
  2497  	case ARFI:	return OPVCC(19,50,0,0);
  2498  	case ARFCI:	return OPVCC(19,51,0,0);
  2499  	case ARFID:	return OPVCC(19,18,0,0);
  2500  	case AHRFID: return OPVCC(19,274,0,0);
  2501  
  2502  	case ARLWMI:	return OPVCC(20,0,0,0);
  2503  	case ARLWMICC: return OPVCC(20,0,0,1);
  2504  	case ARLWNM:	return OPVCC(23,0,0,0);
  2505  	case ARLWNMCC:	return OPVCC(23,0,0,1);
  2506  
  2507  	case ARLDCL:	return OPVCC(30,8,0,0);
  2508  	case ARLDCR:	return OPVCC(30,9,0,0);
  2509  
  2510  	case ASYSCALL:	return OPVCC(17,1,0,0);
  2511  
  2512  	case ASLW:	return OPVCC(31,24,0,0);
  2513  	case ASLWCC:	return OPVCC(31,24,0,1);
  2514  	case ASLD:	return OPVCC(31,27,0,0);
  2515  	case ASLDCC:	return OPVCC(31,27,0,1);
  2516  
  2517  	case ASRAW:	return OPVCC(31,792,0,0);
  2518  	case ASRAWCC:	return OPVCC(31,792,0,1);
  2519  	case ASRAD:	return OPVCC(31,794,0,0);
  2520  	case ASRADCC:	return OPVCC(31,794,0,1);
  2521  
  2522  	case ASRW:	return OPVCC(31,536,0,0);
  2523  	case ASRWCC:	return OPVCC(31,536,0,1);
  2524  	case ASRD:	return OPVCC(31,539,0,0);
  2525  	case ASRDCC:	return OPVCC(31,539,0,1);
  2526  
  2527  	case ASUB:	return OPVCC(31,40,0,0);
  2528  	case ASUBCC:	return OPVCC(31,40,0,1);
  2529  	case ASUBV:	return OPVCC(31,40,1,0);
  2530  	case ASUBVCC:	return OPVCC(31,40,1,1);
  2531  	case ASUBC:	return OPVCC(31,8,0,0);
  2532  	case ASUBCCC:	return OPVCC(31,8,0,1);
  2533  	case ASUBCV:	return OPVCC(31,8,1,0);
  2534  	case ASUBCVCC:	return OPVCC(31,8,1,1);
  2535  	case ASUBE:	return OPVCC(31,136,0,0);
  2536  	case ASUBECC:	return OPVCC(31,136,0,1);
  2537  	case ASUBEV:	return OPVCC(31,136,1,0);
  2538  	case ASUBEVCC:	return OPVCC(31,136,1,1);
  2539  	case ASUBME:	return OPVCC(31,232,0,0);
  2540  	case ASUBMECC:	return OPVCC(31,232,0,1);
  2541  	case ASUBMEV:	return OPVCC(31,232,1,0);
  2542  	case ASUBMEVCC:	return OPVCC(31,232,1,1);
  2543  	case ASUBZE:	return OPVCC(31,200,0,0);
  2544  	case ASUBZECC:	return OPVCC(31,200,0,1);
  2545  	case ASUBZEV:	return OPVCC(31,200,1,0);
  2546  	case ASUBZEVCC:	return OPVCC(31,200,1,1);
  2547  
  2548  	case ASYNC:	return OPVCC(31,598,0,0);
  2549  	case APTESYNC:	return OPVCC(31,598,0,0) | (2<<21);
  2550  
  2551  	case ATLBIE:	return OPVCC(31,306,0,0);
  2552  	case ATLBIEL:	return OPVCC(31,274,0,0);
  2553  	case ATLBSYNC:	return OPVCC(31,566,0,0);
  2554  	case ASLBIA:	return OPVCC(31,498,0,0);
  2555  	case ASLBIE:	return OPVCC(31,434,0,0);
  2556  	case ASLBMFEE:	return OPVCC(31,915,0,0);
  2557  	case ASLBMFEV:	return OPVCC(31,851,0,0);
  2558  	case ASLBMTE:		return OPVCC(31,402,0,0);
  2559  
  2560  	case ATW:	return OPVCC(31,4,0,0);
  2561  	case ATD:	return OPVCC(31,68,0,0);
  2562  
  2563  	case AXOR:	return OPVCC(31,316,0,0);
  2564  	case AXORCC:	return OPVCC(31,316,0,1);
  2565  	}
  2566  	ctxt->diag("bad r/r opcode %A", a);
  2567  	return 0;
  2568  }
  2569  
  2570  static int32
  2571  opirr(Link *ctxt, int a)
  2572  {
  2573  	switch(a) {
  2574  	case AADD:	return OPVCC(14,0,0,0);
  2575  	case AADDC:	return OPVCC(12,0,0,0);
  2576  	case AADDCCC:	return OPVCC(13,0,0,0);
  2577  	case AADD+AEND:	return OPVCC(15,0,0,0);		/* ADDIS/CAU */
  2578  
  2579  	case AANDCC:	return OPVCC(28,0,0,0);
  2580  	case AANDCC+AEND:	return OPVCC(29,0,0,0);		/* ANDIS./ANDIU. */
  2581  
  2582  	case ABR:	return OPVCC(18,0,0,0);
  2583  	case ABL:	return OPVCC(18,0,0,0) | 1;
  2584  	case ADUFFZERO:	return OPVCC(18,0,0,0) | 1;
  2585  	case ADUFFCOPY:	return OPVCC(18,0,0,0) | 1;
  2586  	case ABC:	return OPVCC(16,0,0,0);
  2587  	case ABCL:	return OPVCC(16,0,0,0) | 1;
  2588  
  2589  	case ABEQ:	return AOP_RRR(16<<26,12,2,0);
  2590  	case ABGE:	return AOP_RRR(16<<26,4,0,0);
  2591  	case ABGT:	return AOP_RRR(16<<26,12,1,0);
  2592  	case ABLE:	return AOP_RRR(16<<26,4,1,0);
  2593  	case ABLT:	return AOP_RRR(16<<26,12,0,0);
  2594  	case ABNE:	return AOP_RRR(16<<26,4,2,0);
  2595  	case ABVC:	return AOP_RRR(16<<26,4,3,0);
  2596  	case ABVS:	return AOP_RRR(16<<26,12,3,0);
  2597  
  2598  	case ACMP:	return OPVCC(11,0,0,0)|(1<<21);	/* L=1 */
  2599  	case ACMPU:	return OPVCC(10,0,0,0)|(1<<21);
  2600  	case ACMPW:	return OPVCC(11,0,0,0);	/* L=0 */
  2601  	case ACMPWU:	return OPVCC(10,0,0,0);
  2602  	case ALSW:	return OPVCC(31,597,0,0);
  2603  
  2604  	case AMULLW:	return OPVCC(7,0,0,0);
  2605  
  2606  	case AOR:	return OPVCC(24,0,0,0);
  2607  	case AOR+AEND:	return OPVCC(25,0,0,0);		/* ORIS/ORIU */
  2608  
  2609  	case ARLWMI:	return OPVCC(20,0,0,0);		/* rlwimi */
  2610  	case ARLWMICC:	return OPVCC(20,0,0,1);
  2611  	case ARLDMI:	return OPVCC(30,0,0,0) | (3<<2);	/* rldimi */
  2612  	case ARLDMICC:	return OPVCC(30,0,0,1) | (3<<2);
  2613  
  2614  	case ARLWNM:	return OPVCC(21,0,0,0);		/* rlwinm */
  2615  	case ARLWNMCC:	return OPVCC(21,0,0,1);
  2616  
  2617  	case ARLDCL:	return OPVCC(30,0,0,0);		/* rldicl */
  2618  	case ARLDCLCC:	return OPVCC(30,0,0,1);
  2619  	case ARLDCR:	return OPVCC(30,1,0,0);		/* rldicr */
  2620  	case ARLDCRCC:	return OPVCC(30,1,0,1);
  2621  	case ARLDC:	return OPVCC(30,0,0,0) | (2<<2);
  2622  	case ARLDCCC:	return OPVCC(30,0,0,1) | (2<<2);
  2623  
  2624  	case ASRAW:	return OPVCC(31,824,0,0);
  2625  	case ASRAWCC:	return OPVCC(31,824,0,1);
  2626  	case ASRAD:	return OPVCC(31,(413<<1),0,0);
  2627  	case ASRADCC:	return OPVCC(31,(413<<1),0,1);
  2628  
  2629  	case ASTSW:	return OPVCC(31,725,0,0);
  2630  
  2631  	case ASUBC:	return OPVCC(8,0,0,0);
  2632  
  2633  	case ATW:	return OPVCC(3,0,0,0);
  2634  	case ATD:	return OPVCC(2,0,0,0);
  2635  
  2636  	case AXOR:	return OPVCC(26,0,0,0);		/* XORIL */
  2637  	case AXOR+AEND:	return OPVCC(27,0,0,0);		/* XORIU */
  2638  	}
  2639  	ctxt->diag("bad opcode i/r %A", a);
  2640  	return 0;
  2641  }
  2642  
  2643  /*
  2644   * load o(a),d
  2645   */
  2646  static int32
  2647  opload(Link *ctxt, int a)
  2648  {
  2649  	switch(a) {
  2650  	case AMOVD:	return OPVCC(58,0,0,0);	/* ld */
  2651  	case AMOVDU:	return OPVCC(58,0,0,1);	/* ldu */
  2652  	case AMOVWZ:	return OPVCC(32,0,0,0);		/* lwz */
  2653  	case AMOVWZU:	return OPVCC(33,0,0,0);		/* lwzu */
  2654  	case AMOVW:		return OPVCC(58,0,0,0)|(1<<1);	/* lwa */
  2655  	/* no AMOVWU */
  2656  	case AMOVB:
  2657  	case AMOVBZ:	return OPVCC(34,0,0,0);		/* load */
  2658  	case AMOVBU:
  2659  	case AMOVBZU:	return OPVCC(35,0,0,0);
  2660  	case AFMOVD:	return OPVCC(50,0,0,0);
  2661  	case AFMOVDU:	return OPVCC(51,0,0,0);
  2662  	case AFMOVS:	return OPVCC(48,0,0,0);
  2663  	case AFMOVSU:	return OPVCC(49,0,0,0);
  2664  	case AMOVH:	return OPVCC(42,0,0,0);
  2665  	case AMOVHU:	return OPVCC(43,0,0,0);
  2666  	case AMOVHZ:	return OPVCC(40,0,0,0);
  2667  	case AMOVHZU:	return OPVCC(41,0,0,0);
  2668  	case AMOVMW:	return OPVCC(46,0,0,0);	/* lmw */
  2669  	}
  2670  	ctxt->diag("bad load opcode %A", a);
  2671  	return 0;
  2672  }
  2673  
  2674  /*
  2675   * indexed load a(b),d
  2676   */
  2677  static int32
  2678  oploadx(Link *ctxt, int a)
  2679  {
  2680  	switch(a) {
  2681  	case AMOVWZ: return OPVCC(31,23,0,0);	/* lwzx */
  2682  	case AMOVWZU:	return OPVCC(31,55,0,0); /* lwzux */
  2683  	case AMOVW:	return OPVCC(31,341,0,0);	/* lwax */
  2684  	case AMOVWU:	return OPVCC(31,373,0,0);	/* lwaux */
  2685  	case AMOVB:
  2686  	case AMOVBZ: return OPVCC(31,87,0,0);	/* lbzx */
  2687  	case AMOVBU:
  2688  	case AMOVBZU: return OPVCC(31,119,0,0);	/* lbzux */
  2689  	case AFMOVD:	return OPVCC(31,599,0,0);	/* lfdx */
  2690  	case AFMOVDU:	return OPVCC(31,631,0,0);	/*  lfdux */
  2691  	case AFMOVS:	return OPVCC(31,535,0,0);	/* lfsx */
  2692  	case AFMOVSU:	return OPVCC(31,567,0,0);	/* lfsux */
  2693  	case AMOVH:	return OPVCC(31,343,0,0);	/* lhax */
  2694  	case AMOVHU:	return OPVCC(31,375,0,0);	/* lhaux */
  2695  	case AMOVHBR:	return OPVCC(31,790,0,0);	/* lhbrx */
  2696  	case AMOVWBR:	return OPVCC(31,534,0,0);	/* lwbrx */
  2697  	case AMOVHZ:	return OPVCC(31,279,0,0);	/* lhzx */
  2698  	case AMOVHZU:	return OPVCC(31,311,0,0);	/* lhzux */
  2699  	case AECIWX:	return OPVCC(31,310,0,0);	/* eciwx */
  2700  	case ALWAR:	return OPVCC(31,20,0,0);	/* lwarx */
  2701  	case ALDAR:	return OPVCC(31,84,0,0);
  2702  	case ALSW:	return OPVCC(31,533,0,0);	/* lswx */
  2703  	case AMOVD:	return OPVCC(31,21,0,0);	/* ldx */
  2704  	case AMOVDU:	return OPVCC(31,53,0,0);	/* ldux */
  2705  	}
  2706  	ctxt->diag("bad loadx opcode %A", a);
  2707  	return 0;
  2708  }
  2709  
  2710  /*
  2711   * store s,o(d)
  2712   */
  2713  static int32
  2714  opstore(Link *ctxt, int a)
  2715  {
  2716  	switch(a) {
  2717  	case AMOVB:
  2718  	case AMOVBZ:	return OPVCC(38,0,0,0);	/* stb */
  2719  	case AMOVBU:
  2720  	case AMOVBZU:	return OPVCC(39,0,0,0);	/* stbu */
  2721  	case AFMOVD:	return OPVCC(54,0,0,0);	/* stfd */
  2722  	case AFMOVDU:	return OPVCC(55,0,0,0);	/* stfdu */
  2723  	case AFMOVS:	return OPVCC(52,0,0,0);	/* stfs */
  2724  	case AFMOVSU:	return OPVCC(53,0,0,0);	/* stfsu */
  2725  	case AMOVHZ:
  2726  	case AMOVH:	return OPVCC(44,0,0,0);	/* sth */
  2727  	case AMOVHZU:
  2728  	case AMOVHU:	return OPVCC(45,0,0,0);	/* sthu */
  2729  	case AMOVMW:	return OPVCC(47,0,0,0);	/* stmw */
  2730  	case ASTSW:	return OPVCC(31,725,0,0);	/* stswi */
  2731  	case AMOVWZ:
  2732  	case AMOVW:	return OPVCC(36,0,0,0);	/* stw */
  2733  	case AMOVWZU:
  2734  	case AMOVWU:	return OPVCC(37,0,0,0);	/* stwu */
  2735  	case AMOVD:	return OPVCC(62,0,0,0);	/* std */
  2736  	case AMOVDU:	return OPVCC(62,0,0,1);	/* stdu */
  2737  	}
  2738  	ctxt->diag("unknown store opcode %A", a);
  2739  	return 0;
  2740  }
  2741  
  2742  /*
  2743   * indexed store s,a(b)
  2744   */
  2745  static int32
  2746  opstorex(Link *ctxt, int a)
  2747  {
  2748  	switch(a) {
  2749  	case AMOVB:
  2750  	case AMOVBZ:	return OPVCC(31,215,0,0);	/* stbx */
  2751  	case AMOVBU:
  2752  	case AMOVBZU:	return OPVCC(31,247,0,0);	/* stbux */
  2753  	case AFMOVD:	return OPVCC(31,727,0,0);	/* stfdx */
  2754  	case AFMOVDU:	return OPVCC(31,759,0,0);	/* stfdux */
  2755  	case AFMOVS:	return OPVCC(31,663,0,0);	/* stfsx */
  2756  	case AFMOVSU:	return OPVCC(31,695,0,0);	/* stfsux */
  2757  	case AMOVHZ:
  2758  	case AMOVH:	return OPVCC(31,407,0,0);	/* sthx */
  2759  	case AMOVHBR:	return OPVCC(31,918,0,0);	/* sthbrx */
  2760  	case AMOVHZU:
  2761  	case AMOVHU:	return OPVCC(31,439,0,0);	/* sthux */
  2762  	case AMOVWZ:
  2763  	case AMOVW:	return OPVCC(31,151,0,0);	/* stwx */
  2764  	case AMOVWZU:
  2765  	case AMOVWU:	return OPVCC(31,183,0,0);	/* stwux */
  2766  	case ASTSW:	return OPVCC(31,661,0,0);	/* stswx */
  2767  	case AMOVWBR:	return OPVCC(31,662,0,0);	/* stwbrx */
  2768  	case ASTWCCC:	return OPVCC(31,150,0,1);	/* stwcx. */
  2769  	case ASTDCCC:	return OPVCC(31,214,0,1);	/* stwdx. */
  2770  	case AECOWX:	return OPVCC(31,438,0,0);	/* ecowx */
  2771  	case AMOVD:	return OPVCC(31,149,0,0);	/* stdx */
  2772  	case AMOVDU:	return OPVCC(31,181,0,0);	/* stdux */
  2773  	}
  2774  	ctxt->diag("unknown storex opcode %A", a);
  2775  	return 0;
  2776  }
  2777