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