github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/cmd/internal/obj/arm/asm5.go (about)

     1  // Inferno utils/5l/span.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/5l/span.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package arm
    32  
    33  import (
    34  	"cmd/internal/obj"
    35  	"cmd/internal/objabi"
    36  	"fmt"
    37  	"log"
    38  	"math"
    39  	"sort"
    40  )
    41  
    42  // ctxt5 holds state while assembling a single function.
    43  // Each function gets a fresh ctxt5.
    44  // This allows for multiple functions to be safely concurrently assembled.
    45  type ctxt5 struct {
    46  	ctxt       *obj.Link
    47  	newprog    obj.ProgAlloc
    48  	cursym     *obj.LSym
    49  	printp     *obj.Prog
    50  	blitrl     *obj.Prog
    51  	elitrl     *obj.Prog
    52  	autosize   int64
    53  	instoffset int64
    54  	pc         int64
    55  	pool       struct {
    56  		start uint32
    57  		size  uint32
    58  		extra uint32
    59  	}
    60  }
    61  
    62  type Optab struct {
    63  	as       obj.As
    64  	a1       uint8
    65  	a2       int8
    66  	a3       uint8
    67  	type_    uint8
    68  	size     int8
    69  	param    int16
    70  	flag     int8
    71  	pcrelsiz uint8
    72  }
    73  
    74  type Opcross [32][2][32]uint8
    75  
    76  const (
    77  	LFROM  = 1 << 0
    78  	LTO    = 1 << 1
    79  	LPOOL  = 1 << 2
    80  	LPCREL = 1 << 3
    81  )
    82  
    83  var optab = []Optab{
    84  	/* struct Optab:
    85  	OPCODE,	from, prog->reg, to,		 type,size,param,flag */
    86  	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
    87  	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
    88  	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
    89  	{AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
    90  	{AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
    91  	{AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
    92  	{AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
    93  	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
    94  	{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
    95  	{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
    96  	{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
    97  	{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
    98  	{AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
    99  	{AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
   100  	{AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
   101  	{AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
   102  	{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
   103  	{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
   104  	{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
   105  	{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   106  	{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   107  	{AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   108  	{AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   109  	{AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   110  	{AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   111  	{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   112  	{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
   113  	{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
   114  	{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
   115  	{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   116  	{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
   117  	{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   118  	{ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // prediction hinted form, hint ignored
   119  
   120  	{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
   121  	{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
   122  	{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
   123  	{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
   124  	{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
   125  	{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
   126  	{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
   127  	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
   128  	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
   129  	{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   130  	{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
   131  	{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
   132  	{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
   133  	{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
   134  	{AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0},
   135  	{AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0},
   136  	{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
   137  	{AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
   138  	{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
   139  	{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
   140  	{AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
   141  	{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   142  	{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   143  	{AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   144  	{AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   145  	{AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   146  	{AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   147  	{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
   148  	{AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   149  	{AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   150  	{AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   151  	{AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   152  	{AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
   153  	{AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   154  	{AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
   155  	{ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
   156  	{AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0},
   157  	{AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0},
   158  	{AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0},
   159  	{AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0},
   160  	{AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0},
   161  	{AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0},
   162  	{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
   163  	{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
   164  	{AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
   165  	{AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
   166  	{AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
   167  	{AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
   168  	{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
   169  	{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
   170  	{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   171  	{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
   172  	{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
   173  	{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   174  	{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
   175  	{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
   176  	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
   177  	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
   178  	{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
   179  	{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
   180  	{ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0},
   181  	{ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0},
   182  	{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
   183  	{ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0},  // width in From, LSB in From3
   184  	{ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0}, // width in From, LSB in From3
   185  	{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
   186  	{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
   187  	{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
   188  	{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
   189  	{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
   190  	{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
   191  	{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
   192  	{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
   193  	{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   194  	{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   195  	{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   196  	{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   197  	{AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0},
   198  	{AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0},
   199  	{AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   200  	{AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   201  	{AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   202  	{AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   203  	{AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   204  	{AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   205  	{AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
   206  	{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   207  	{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   208  	{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
   209  	{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   210  	{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   211  	{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
   212  	{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   213  	{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   214  	{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
   215  	{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   216  	{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   217  	{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
   218  	{AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0},
   219  	{AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0},
   220  	{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   221  	{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   222  	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
   223  	{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   224  	{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   225  	{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
   226  	{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
   227  	{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
   228  	{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
   229  	{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
   230  	{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
   231  	{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0},
   232  	{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
   233  	{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
   234  	{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
   235  	{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
   236  	{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
   237  	{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
   238  	{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
   239  	{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
   240  	{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
   241  	{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
   242  	{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
   243  	{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
   244  	{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   245  	{AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0},
   246  	{AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   247  	{ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   248  	{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
   249  	{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
   250  	{AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
   251  	{AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
   252  	{AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
   253  	{AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
   254  	{AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
   255  	{AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
   256  	{AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
   257  	{AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
   258  	{AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
   259  	{AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
   260  	{AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
   261  	{AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
   262  	{AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
   263  	{AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
   264  	{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
   265  	{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
   266  	{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
   267  	{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
   268  	{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
   269  	{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
   270  	{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
   271  	{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
   272  	{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
   273  	{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
   274  	{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
   275  	{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
   276  	{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
   277  	{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
   278  	{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
   279  	{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
   280  	{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
   281  	{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
   282  	{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
   283  	{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
   284  	{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
   285  	{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
   286  	{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
   287  	{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
   288  	{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
   289  	{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
   290  	{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
   291  	{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
   292  	{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
   293  	{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
   294  	{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
   295  	{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
   296  	{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
   297  	{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
   298  	{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
   299  	{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
   300  	{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
   301  	{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
   302  	{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
   303  	{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
   304  	{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
   305  	{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
   306  	{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
   307  	{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
   308  	{ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0},
   309  	{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
   310  	{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
   311  	{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
   312  	{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
   313  	{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
   314  	{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
   315  	{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
   316  	{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
   317  	{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
   318  	{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
   319  	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
   320  	{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
   321  	{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
   322  	{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
   323  	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
   324  	{obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
   325  	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   326  	{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
   327  	{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
   328  
   329  	{ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
   330  	{ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
   331  	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
   332  }
   333  
   334  var oprange [ALAST & obj.AMask][]Optab
   335  
   336  var xcmp [C_GOK + 1][C_GOK + 1]bool
   337  
   338  var (
   339  	deferreturn *obj.LSym
   340  	symdiv      *obj.LSym
   341  	symdivu     *obj.LSym
   342  	symmod      *obj.LSym
   343  	symmodu     *obj.LSym
   344  )
   345  
   346  // Note about encoding: Prog.scond holds the condition encoding,
   347  // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
   348  // The code that shifts the value << 28 has the responsibility
   349  // for XORing with C_SCOND_XOR too.
   350  
   351  // asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
   352  // It returns the total number of bytes put in out, and it can change
   353  // p->pc if extra padding is necessary.
   354  // In rare cases, asmoutnacl might split p into two instructions.
   355  // origPC is the PC for this Prog (no padding is taken into account).
   356  func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) int {
   357  	size := int(o.size)
   358  
   359  	// instruction specific
   360  	switch p.As {
   361  	default:
   362  		if out != nil {
   363  			c.asmout(p, o, out)
   364  		}
   365  
   366  	case ADATABUNDLE, // align to 16-byte boundary
   367  		ADATABUNDLEEND: // zero width instruction, just to align next instruction to 16-byte boundary
   368  		p.Pc = (p.Pc + 15) &^ 15
   369  
   370  		if out != nil {
   371  			c.asmout(p, o, out)
   372  		}
   373  
   374  	case obj.AUNDEF,
   375  		APLD:
   376  		size = 4
   377  		if out != nil {
   378  			switch p.As {
   379  			case obj.AUNDEF:
   380  				out[0] = 0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
   381  
   382  			case APLD:
   383  				out[0] = 0xe1a01001 // (MOVW R1, R1)
   384  			}
   385  		}
   386  
   387  	case AB, ABL:
   388  		if p.To.Type != obj.TYPE_MEM {
   389  			if out != nil {
   390  				c.asmout(p, o, out)
   391  			}
   392  		} else {
   393  			if p.To.Offset != 0 || size != 4 || p.To.Reg > REG_R15 || p.To.Reg < REG_R0 {
   394  				c.ctxt.Diag("unsupported instruction: %v", p)
   395  			}
   396  			if p.Pc&15 == 12 {
   397  				p.Pc += 4
   398  			}
   399  			if out != nil {
   400  				out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c0013f | (uint32(p.To.Reg)&15)<<12 | (uint32(p.To.Reg)&15)<<16 // BIC $0xc000000f, Rx
   401  				if p.As == AB {
   402  					out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff10 | (uint32(p.To.Reg)&15)<<0 // BX Rx
   403  				} else { // ABL
   404  					out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff30 | (uint32(p.To.Reg)&15)<<0 // BLX Rx
   405  				}
   406  			}
   407  
   408  			size = 8
   409  		}
   410  
   411  		// align the last instruction (the actual BL) to the last instruction in a bundle
   412  		if p.As == ABL {
   413  			if p.To.Sym == deferreturn {
   414  				p.Pc = ((int64(origPC) + 15) &^ 15) + 16 - int64(size)
   415  			} else {
   416  				p.Pc += (16 - ((p.Pc + int64(size)) & 15)) & 15
   417  			}
   418  		}
   419  
   420  	case ALDREX,
   421  		ALDREXD,
   422  		AMOVB,
   423  		AMOVBS,
   424  		AMOVBU,
   425  		AMOVD,
   426  		AMOVF,
   427  		AMOVH,
   428  		AMOVHS,
   429  		AMOVHU,
   430  		AMOVM,
   431  		AMOVW,
   432  		ASTREX,
   433  		ASTREXD:
   434  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 && p.From.Reg == REG_R13 { // MOVW.W x(R13), PC
   435  			if out != nil {
   436  				c.asmout(p, o, out)
   437  			}
   438  			if size == 4 {
   439  				if out != nil {
   440  					// Note: 5c and 5g reg.c know that DIV/MOD smashes R12
   441  					// so that this return instruction expansion is valid.
   442  					out[0] = out[0] &^ 0x3000                                         // change PC to R12
   443  					out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
   444  					out[2] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff1c // BX R12
   445  				}
   446  
   447  				size += 8
   448  				if (p.Pc+int64(size))&15 == 4 {
   449  					p.Pc += 4
   450  				}
   451  				break
   452  			} else {
   453  				// if the instruction used more than 4 bytes, then it must have used a very large
   454  				// offset to update R13, so we need to additionally mask R13.
   455  				if out != nil {
   456  					out[size/4-1] &^= 0x3000                                                 // change PC to R12
   457  					out[size/4] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03cdd103   // BIC $0xc0000000, R13
   458  					out[size/4+1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
   459  					out[size/4+2] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff1c // BX R12
   460  				}
   461  
   462  				// p->pc+size is only ok at 4 or 12 mod 16.
   463  				if (p.Pc+int64(size))%8 == 0 {
   464  					p.Pc += 4
   465  				}
   466  				size += 12
   467  				break
   468  			}
   469  		}
   470  
   471  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 {
   472  			c.ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p)
   473  		}
   474  
   475  		if p.To.Type == obj.TYPE_MEM && p.To.Reg == REG_R13 && (p.Scond&C_WBIT != 0) && size > 4 {
   476  			// function prolog with very large frame size: MOVW.W R14,-100004(R13)
   477  			// split it into two instructions:
   478  			// 	ADD $-100004, R13
   479  			// 	MOVW R14, 0(R13)
   480  			q := c.newprog()
   481  
   482  			p.Scond &^= C_WBIT
   483  			*q = *p
   484  			a := &p.To
   485  			var a2 *obj.Addr
   486  			if p.To.Type == obj.TYPE_MEM {
   487  				a2 = &q.To
   488  			} else {
   489  				a2 = &q.From
   490  			}
   491  			nocache(q)
   492  			nocache(p)
   493  
   494  			// insert q after p
   495  			q.Link = p.Link
   496  
   497  			p.Link = q
   498  			q.Pcond = nil
   499  
   500  			// make p into ADD $X, R13
   501  			p.As = AADD
   502  
   503  			p.From = *a
   504  			p.From.Reg = 0
   505  			p.From.Type = obj.TYPE_CONST
   506  			p.To = obj.Addr{}
   507  			p.To.Type = obj.TYPE_REG
   508  			p.To.Reg = REG_R13
   509  
   510  			// make q into p but load/store from 0(R13)
   511  			q.Spadj = 0
   512  
   513  			*a2 = obj.Addr{}
   514  			a2.Type = obj.TYPE_MEM
   515  			a2.Reg = REG_R13
   516  			a2.Sym = nil
   517  			a2.Offset = 0
   518  			size = int(c.oplook(p).size)
   519  			break
   520  		}
   521  
   522  		if (p.To.Type == obj.TYPE_MEM && p.To.Reg != REG_R9) || // MOVW Rx, X(Ry), y != 9
   523  			(p.From.Type == obj.TYPE_MEM && p.From.Reg != REG_R9) { // MOVW X(Rx), Ry, x != 9
   524  			var a *obj.Addr
   525  			if p.To.Type == obj.TYPE_MEM {
   526  				a = &p.To
   527  			} else {
   528  				a = &p.From
   529  			}
   530  			reg := int(a.Reg)
   531  			if size == 4 {
   532  				// if addr.reg == 0, then it is probably load from x(FP) with small x, no need to modify.
   533  				if reg == 0 {
   534  					if out != nil {
   535  						c.asmout(p, o, out)
   536  					}
   537  				} else {
   538  					if out != nil {
   539  						out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c00103 | (uint32(reg)&15)<<16 | (uint32(reg)&15)<<12 // BIC $0xc0000000, Rx
   540  					}
   541  					if p.Pc&15 == 12 {
   542  						p.Pc += 4
   543  					}
   544  					size += 4
   545  					if out != nil {
   546  						c.asmout(p, o, out[1:])
   547  					}
   548  				}
   549  
   550  				break
   551  			} else {
   552  				// if a load/store instruction takes more than 1 word to implement, then
   553  				// we need to separate the instruction into two:
   554  				// 1. explicitly load the address into R11.
   555  				// 2. load/store from R11.
   556  				// This won't handle .W/.P, so we should reject such code.
   557  				if p.Scond&(C_PBIT|C_WBIT) != 0 {
   558  					c.ctxt.Diag("unsupported instruction (.P/.W): %v", p)
   559  				}
   560  				q := c.newprog()
   561  				*q = *p
   562  				var a2 *obj.Addr
   563  				if p.To.Type == obj.TYPE_MEM {
   564  					a2 = &q.To
   565  				} else {
   566  					a2 = &q.From
   567  				}
   568  				nocache(q)
   569  				nocache(p)
   570  
   571  				// insert q after p
   572  				q.Link = p.Link
   573  
   574  				p.Link = q
   575  				q.Pcond = nil
   576  
   577  				// make p into MOVW $X(R), R11
   578  				p.As = AMOVW
   579  
   580  				p.From = *a
   581  				p.From.Type = obj.TYPE_ADDR
   582  				p.To = obj.Addr{}
   583  				p.To.Type = obj.TYPE_REG
   584  				p.To.Reg = REG_R11
   585  
   586  				// make q into p but load/store from 0(R11)
   587  				*a2 = obj.Addr{}
   588  
   589  				a2.Type = obj.TYPE_MEM
   590  				a2.Reg = REG_R11
   591  				a2.Sym = nil
   592  				a2.Offset = 0
   593  				size = int(c.oplook(p).size)
   594  				break
   595  			}
   596  		} else if out != nil {
   597  			c.asmout(p, o, out)
   598  		}
   599  	}
   600  
   601  	// destination register specific
   602  	if p.To.Type == obj.TYPE_REG {
   603  		switch p.To.Reg {
   604  		case REG_R9:
   605  			c.ctxt.Diag("invalid instruction, cannot write to R9: %v", p)
   606  
   607  		case REG_R13:
   608  			if out != nil {
   609  				out[size/4] = 0xe3cdd103 // BIC $0xc0000000, R13
   610  			}
   611  			if (p.Pc+int64(size))&15 == 0 {
   612  				p.Pc += 4
   613  			}
   614  			size += 4
   615  		}
   616  	}
   617  
   618  	return size
   619  }
   620  
   621  const (
   622  	T_SBIT = 1 << 0
   623  	T_PBIT = 1 << 1
   624  	T_WBIT = 1 << 2
   625  )
   626  
   627  var mayHaveSuffix = map[obj.As]uint8{
   628  	// bit logic
   629  	AAND: T_SBIT,
   630  	AEOR: T_SBIT,
   631  	AORR: T_SBIT,
   632  	ABIC: T_SBIT,
   633  	// arithmatic
   634  	ASUB: T_SBIT,
   635  	AADD: T_SBIT,
   636  	ASBC: T_SBIT,
   637  	AADC: T_SBIT,
   638  	ARSB: T_SBIT,
   639  	ARSC: T_SBIT,
   640  	// mov
   641  	AMVN:   T_SBIT,
   642  	AMOVW:  T_SBIT | T_PBIT | T_WBIT,
   643  	AMOVB:  T_SBIT | T_PBIT | T_WBIT,
   644  	AMOVBS: T_SBIT | T_PBIT | T_WBIT,
   645  	AMOVBU: T_SBIT | T_PBIT | T_WBIT,
   646  	AMOVH:  T_SBIT | T_PBIT | T_WBIT,
   647  	AMOVHS: T_SBIT | T_PBIT | T_WBIT,
   648  	AMOVHU: T_SBIT | T_PBIT | T_WBIT,
   649  	AMOVM:  T_PBIT | T_WBIT,
   650  	// shift
   651  	ASRL: T_SBIT,
   652  	ASRA: T_SBIT,
   653  	ASLL: T_SBIT,
   654  	// mul
   655  	AMUL:   T_SBIT,
   656  	AMULU:  T_SBIT,
   657  	AMULL:  T_SBIT,
   658  	AMULLU: T_SBIT,
   659  	// mula
   660  	AMULA:   T_SBIT,
   661  	AMULAL:  T_SBIT,
   662  	AMULALU: T_SBIT,
   663  	// MRC/MCR
   664  	AMRC: T_SBIT,
   665  }
   666  
   667  func checkBits(ctxt *obj.Link, p *obj.Prog) {
   668  	if p.Scond&C_SBIT != 0 && mayHaveSuffix[p.As]&T_SBIT == 0 {
   669  		ctxt.Diag("invalid .S suffix: %v", p)
   670  	}
   671  	if p.Scond&C_PBIT != 0 && mayHaveSuffix[p.As]&T_PBIT == 0 {
   672  		ctxt.Diag("invalid .P suffix: %v", p)
   673  	}
   674  	if p.Scond&C_WBIT != 0 && mayHaveSuffix[p.As]&T_WBIT == 0 {
   675  		ctxt.Diag("invalid .W suffix: %v", p)
   676  	}
   677  }
   678  
   679  func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   680  	var p *obj.Prog
   681  	var op *obj.Prog
   682  
   683  	p = cursym.Func.Text
   684  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   685  		return
   686  	}
   687  
   688  	if oprange[AAND&obj.AMask] == nil {
   689  		ctxt.Diag("arm ops not initialized, call arm.buildop first")
   690  	}
   691  
   692  	c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4}
   693  	pc := int32(0)
   694  
   695  	op = p
   696  	p = p.Link
   697  	var i int
   698  	var m int
   699  	var o *Optab
   700  	for ; p != nil || c.blitrl != nil; op, p = p, p.Link {
   701  		if p == nil {
   702  			if c.checkpool(op, 0) {
   703  				p = op
   704  				continue
   705  			}
   706  
   707  			// can't happen: blitrl is not nil, but checkpool didn't flushpool
   708  			ctxt.Diag("internal inconsistency")
   709  
   710  			break
   711  		}
   712  
   713  		p.Pc = int64(pc)
   714  		o = c.oplook(p)
   715  		if ctxt.Headtype != objabi.Hnacl {
   716  			m = int(o.size)
   717  		} else {
   718  			m = c.asmoutnacl(pc, p, o, nil)
   719  			pc = int32(p.Pc) // asmoutnacl might change pc for alignment
   720  			o = c.oplook(p)  // asmoutnacl might change p in rare cases
   721  		}
   722  
   723  		if m%4 != 0 || p.Pc%4 != 0 {
   724  			ctxt.Diag("!pc invalid: %v size=%d", p, m)
   725  		}
   726  
   727  		// must check literal pool here in case p generates many instructions
   728  		if c.blitrl != nil {
   729  			i = m
   730  			if c.checkpool(op, i) {
   731  				p = op
   732  				continue
   733  			}
   734  		}
   735  
   736  		if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) {
   737  			ctxt.Diag("zero-width instruction\n%v", p)
   738  			continue
   739  		}
   740  
   741  		switch o.flag & (LFROM | LTO | LPOOL) {
   742  		case LFROM:
   743  			c.addpool(p, &p.From)
   744  
   745  		case LTO:
   746  			c.addpool(p, &p.To)
   747  
   748  		case LPOOL:
   749  			if p.Scond&C_SCOND == C_SCOND_NONE {
   750  				c.flushpool(p, 0, 0)
   751  			}
   752  		}
   753  
   754  		if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
   755  			c.flushpool(p, 0, 0)
   756  		}
   757  
   758  		checkBits(ctxt, p)
   759  
   760  		pc += int32(m)
   761  	}
   762  
   763  	c.cursym.Size = int64(pc)
   764  
   765  	/*
   766  	 * if any procedure is large enough to
   767  	 * generate a large SBRA branch, then
   768  	 * generate extra passes putting branches
   769  	 * around jmps to fix. this is rare.
   770  	 */
   771  	times := 0
   772  
   773  	var bflag int
   774  	var opc int32
   775  	var out [6 + 3]uint32
   776  	for {
   777  		bflag = 0
   778  		pc = 0
   779  		times++
   780  		c.cursym.Func.Text.Pc = 0 // force re-layout the code.
   781  		for p = c.cursym.Func.Text; p != nil; p = p.Link {
   782  			o = c.oplook(p)
   783  			if int64(pc) > p.Pc {
   784  				p.Pc = int64(pc)
   785  			}
   786  
   787  			/* very large branches
   788  			if(o->type == 6 && p->pcond) {
   789  				otxt = p->pcond->pc - c;
   790  				if(otxt < 0)
   791  					otxt = -otxt;
   792  				if(otxt >= (1L<<17) - 10) {
   793  					q = emallocz(sizeof(Prog));
   794  					q->link = p->link;
   795  					p->link = q;
   796  					q->as = AB;
   797  					q->to.type = TYPE_BRANCH;
   798  					q->pcond = p->pcond;
   799  					p->pcond = q;
   800  					q = emallocz(sizeof(Prog));
   801  					q->link = p->link;
   802  					p->link = q;
   803  					q->as = AB;
   804  					q->to.type = TYPE_BRANCH;
   805  					q->pcond = q->link->link;
   806  					bflag = 1;
   807  				}
   808  			}
   809  			*/
   810  			opc = int32(p.Pc)
   811  
   812  			if ctxt.Headtype != objabi.Hnacl {
   813  				m = int(o.size)
   814  			} else {
   815  				m = c.asmoutnacl(pc, p, o, nil)
   816  			}
   817  			if p.Pc != int64(opc) {
   818  				bflag = 1
   819  			}
   820  
   821  			//print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
   822  			pc = int32(p.Pc + int64(m))
   823  
   824  			if m%4 != 0 || p.Pc%4 != 0 {
   825  				ctxt.Diag("pc invalid: %v size=%d", p, m)
   826  			}
   827  
   828  			if m/4 > len(out) {
   829  				ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
   830  			}
   831  			if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) {
   832  				if p.As == obj.ATEXT {
   833  					c.autosize = p.To.Offset + 4
   834  					continue
   835  				}
   836  
   837  				ctxt.Diag("zero-width instruction\n%v", p)
   838  				continue
   839  			}
   840  		}
   841  
   842  		c.cursym.Size = int64(pc)
   843  		if bflag == 0 {
   844  			break
   845  		}
   846  	}
   847  
   848  	if pc%4 != 0 {
   849  		ctxt.Diag("sym->size=%d, invalid", pc)
   850  	}
   851  
   852  	/*
   853  	 * lay out the code.  all the pc-relative code references,
   854  	 * even cross-function, are resolved now;
   855  	 * only data references need to be relocated.
   856  	 * with more work we could leave cross-function
   857  	 * code references to be relocated too, and then
   858  	 * perhaps we'd be able to parallelize the span loop above.
   859  	 */
   860  
   861  	p = c.cursym.Func.Text
   862  	c.autosize = p.To.Offset + 4
   863  	c.cursym.Grow(c.cursym.Size)
   864  
   865  	bp := c.cursym.P
   866  	pc = int32(p.Pc) // even p->link might need extra padding
   867  	var v int
   868  	for p = p.Link; p != nil; p = p.Link {
   869  		c.pc = p.Pc
   870  		o = c.oplook(p)
   871  		opc = int32(p.Pc)
   872  		if ctxt.Headtype != objabi.Hnacl {
   873  			c.asmout(p, o, out[:])
   874  			m = int(o.size)
   875  		} else {
   876  			m = c.asmoutnacl(pc, p, o, out[:])
   877  			if int64(opc) != p.Pc {
   878  				ctxt.Diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %v", opc, int32(p.Pc), p)
   879  			}
   880  		}
   881  
   882  		if m%4 != 0 || p.Pc%4 != 0 {
   883  			ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
   884  		}
   885  
   886  		if int64(pc) > p.Pc {
   887  			ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p)
   888  		}
   889  		for int64(pc) != p.Pc {
   890  			// emit 0xe1a00000 (MOVW R0, R0)
   891  			bp[0] = 0x00
   892  			bp = bp[1:]
   893  
   894  			bp[0] = 0x00
   895  			bp = bp[1:]
   896  			bp[0] = 0xa0
   897  			bp = bp[1:]
   898  			bp[0] = 0xe1
   899  			bp = bp[1:]
   900  			pc += 4
   901  		}
   902  
   903  		for i = 0; i < m/4; i++ {
   904  			v = int(out[i])
   905  			bp[0] = byte(v)
   906  			bp = bp[1:]
   907  			bp[0] = byte(v >> 8)
   908  			bp = bp[1:]
   909  			bp[0] = byte(v >> 16)
   910  			bp = bp[1:]
   911  			bp[0] = byte(v >> 24)
   912  			bp = bp[1:]
   913  		}
   914  
   915  		pc += int32(m)
   916  	}
   917  }
   918  
   919  /*
   920   * when the first reference to the literal pool threatens
   921   * to go out of range of a 12-bit PC-relative offset,
   922   * drop the pool now, and branch round it.
   923   * this happens only in extended basic blocks that exceed 4k.
   924   */
   925  func (c *ctxt5) checkpool(p *obj.Prog, sz int) bool {
   926  	if c.pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+c.pool.size)-int64(c.pool.start+8))) == 0 {
   927  		return c.flushpool(p, 1, 0)
   928  	} else if p.Link == nil {
   929  		return c.flushpool(p, 2, 0)
   930  	}
   931  	return false
   932  }
   933  
   934  func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool {
   935  	if c.blitrl != nil {
   936  		if skip != 0 {
   937  			if false && skip == 1 {
   938  				fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
   939  			}
   940  			q := c.newprog()
   941  			q.As = AB
   942  			q.To.Type = obj.TYPE_BRANCH
   943  			q.Pcond = p.Link
   944  			q.Link = c.blitrl
   945  			q.Pos = p.Pos
   946  			c.blitrl = q
   947  		} else if force == 0 && (p.Pc+int64(12+c.pool.size)-int64(c.pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size
   948  			return false
   949  		}
   950  		if c.ctxt.Headtype == objabi.Hnacl && c.pool.size%16 != 0 {
   951  			// if pool is not multiple of 16 bytes, add an alignment marker
   952  			q := c.newprog()
   953  
   954  			q.As = ADATABUNDLEEND
   955  			c.elitrl.Link = q
   956  			c.elitrl = q
   957  		}
   958  
   959  		// The line number for constant pool entries doesn't really matter.
   960  		// We set it to the line number of the preceding instruction so that
   961  		// there are no deltas to encode in the pc-line tables.
   962  		for q := c.blitrl; q != nil; q = q.Link {
   963  			q.Pos = p.Pos
   964  		}
   965  
   966  		c.elitrl.Link = p.Link
   967  		p.Link = c.blitrl
   968  
   969  		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
   970  		c.elitrl = nil
   971  		c.pool.size = 0
   972  		c.pool.start = 0
   973  		c.pool.extra = 0
   974  		return true
   975  	}
   976  
   977  	return false
   978  }
   979  
   980  func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) {
   981  	t := c.newprog()
   982  	t.As = AWORD
   983  
   984  	switch c.aclass(a) {
   985  	default:
   986  		t.To.Offset = a.Offset
   987  		t.To.Sym = a.Sym
   988  		t.To.Type = a.Type
   989  		t.To.Name = a.Name
   990  
   991  		if c.ctxt.Flag_shared && t.To.Sym != nil {
   992  			t.Rel = p
   993  		}
   994  
   995  	case C_SROREG,
   996  		C_LOREG,
   997  		C_ROREG,
   998  		C_FOREG,
   999  		C_SOREG,
  1000  		C_HOREG,
  1001  		C_FAUTO,
  1002  		C_SAUTO,
  1003  		C_LAUTO,
  1004  		C_LACON:
  1005  		t.To.Type = obj.TYPE_CONST
  1006  		t.To.Offset = c.instoffset
  1007  	}
  1008  
  1009  	if t.Rel == nil {
  1010  		for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
  1011  			if q.Rel == nil && q.To == t.To {
  1012  				p.Pcond = q
  1013  				return
  1014  			}
  1015  		}
  1016  	}
  1017  
  1018  	if c.ctxt.Headtype == objabi.Hnacl && c.pool.size%16 == 0 {
  1019  		// start a new data bundle
  1020  		q := c.newprog()
  1021  		q.As = ADATABUNDLE
  1022  		q.Pc = int64(c.pool.size)
  1023  		c.pool.size += 4
  1024  		if c.blitrl == nil {
  1025  			c.blitrl = q
  1026  			c.pool.start = uint32(p.Pc)
  1027  		} else {
  1028  			c.elitrl.Link = q
  1029  		}
  1030  
  1031  		c.elitrl = q
  1032  	}
  1033  
  1034  	q := c.newprog()
  1035  	*q = *t
  1036  	q.Pc = int64(c.pool.size)
  1037  
  1038  	if c.blitrl == nil {
  1039  		c.blitrl = q
  1040  		c.pool.start = uint32(p.Pc)
  1041  	} else {
  1042  		c.elitrl.Link = q
  1043  	}
  1044  	c.elitrl = q
  1045  	c.pool.size += 4
  1046  
  1047  	p.Pcond = q
  1048  }
  1049  
  1050  func (c *ctxt5) regoff(a *obj.Addr) int32 {
  1051  	c.instoffset = 0
  1052  	c.aclass(a)
  1053  	return int32(c.instoffset)
  1054  }
  1055  
  1056  func immrot(v uint32) int32 {
  1057  	for i := 0; i < 16; i++ {
  1058  		if v&^0xff == 0 {
  1059  			return int32(uint32(int32(i)<<8) | v | 1<<25)
  1060  		}
  1061  		v = v<<2 | v>>30
  1062  	}
  1063  
  1064  	return 0
  1065  }
  1066  
  1067  // immrot2a returns bits encoding the immediate constant fields of two instructions,
  1068  // such that the encoded constants x, y satisfy x|y==v, x&y==0.
  1069  // Returns 0,0 if no such decomposition of v exists.
  1070  func immrot2a(v uint32) (uint32, uint32) {
  1071  	for i := uint(1); i < 32; i++ {
  1072  		m := uint32(1<<i - 1)
  1073  		if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 {
  1074  			return uint32(x), uint32(y)
  1075  		}
  1076  	}
  1077  	// TODO: handle some more cases, like where
  1078  	// the wraparound from the rotate could help.
  1079  	return 0, 0
  1080  }
  1081  
  1082  // immrot2s returns bits encoding the immediate constant fields of two instructions,
  1083  // such that the encoded constants y, x satisfy y-x==v, y&x==0.
  1084  // Returns 0,0 if no such decomposition of v exists.
  1085  func immrot2s(v uint32) (uint32, uint32) {
  1086  	if immrot(v) != 0 {
  1087  		return v, 0
  1088  	}
  1089  	// suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
  1090  	// omit trailing 00
  1091  	var i uint32
  1092  	for i = 2; i < 32; i += 2 {
  1093  		if v&(1<<i-1) != 0 {
  1094  			break
  1095  		}
  1096  	}
  1097  	// i must be <= 24, then adjust i just above lower 8 effective bits of v
  1098  	i += 6
  1099  	// let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
  1100  	x := 1<<i - v&(1<<i-1)
  1101  	y := v + x
  1102  	if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 {
  1103  		return y, x
  1104  	}
  1105  	return 0, 0
  1106  }
  1107  
  1108  func immaddr(v int32) int32 {
  1109  	if v >= 0 && v <= 0xfff {
  1110  		return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
  1111  	}
  1112  	if v >= -0xfff && v < 0 {
  1113  		return -v&0xfff | 1<<24 /* pre indexing */
  1114  	}
  1115  	return 0
  1116  }
  1117  
  1118  func immfloat(v int32) bool {
  1119  	return v&0xC03 == 0 /* offset will fit in floating-point load/store */
  1120  }
  1121  
  1122  func immhalf(v int32) bool {
  1123  	if v >= 0 && v <= 0xff {
  1124  		return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
  1125  	}
  1126  	if v >= -0xff && v < 0 {
  1127  		return -v&0xff|1<<24 != 0 /* pre indexing */
  1128  	}
  1129  	return false
  1130  }
  1131  
  1132  func (c *ctxt5) aclass(a *obj.Addr) int {
  1133  	switch a.Type {
  1134  	case obj.TYPE_NONE:
  1135  		return C_NONE
  1136  
  1137  	case obj.TYPE_REG:
  1138  		c.instoffset = 0
  1139  		if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
  1140  			return C_REG
  1141  		}
  1142  		if REG_F0 <= a.Reg && a.Reg <= REG_F15 {
  1143  			return C_FREG
  1144  		}
  1145  		if a.Reg == REG_FPSR || a.Reg == REG_FPCR {
  1146  			return C_FCR
  1147  		}
  1148  		if a.Reg == REG_CPSR || a.Reg == REG_SPSR {
  1149  			return C_PSR
  1150  		}
  1151  		return C_GOK
  1152  
  1153  	case obj.TYPE_REGREG:
  1154  		return C_REGREG
  1155  
  1156  	case obj.TYPE_REGREG2:
  1157  		return C_REGREG2
  1158  
  1159  	case obj.TYPE_REGLIST:
  1160  		return C_REGLIST
  1161  
  1162  	case obj.TYPE_SHIFT:
  1163  		if a.Reg == 0 {
  1164  			// register shift R>>i
  1165  			return C_SHIFT
  1166  		} else {
  1167  			// memory address with shifted offset R>>i(R)
  1168  			return C_SHIFTADDR
  1169  		}
  1170  
  1171  	case obj.TYPE_MEM:
  1172  		switch a.Name {
  1173  		case obj.NAME_EXTERN,
  1174  			obj.NAME_GOTREF,
  1175  			obj.NAME_STATIC:
  1176  			if a.Sym == nil || a.Sym.Name == "" {
  1177  				fmt.Printf("null sym external\n")
  1178  				return C_GOK
  1179  			}
  1180  
  1181  			c.instoffset = 0 // s.b. unused but just in case
  1182  			if a.Sym.Type == objabi.STLSBSS {
  1183  				if c.ctxt.Flag_shared {
  1184  					return C_TLS_IE
  1185  				} else {
  1186  					return C_TLS_LE
  1187  				}
  1188  			}
  1189  
  1190  			return C_ADDR
  1191  
  1192  		case obj.NAME_AUTO:
  1193  			if a.Reg == REGSP {
  1194  				// unset base register for better printing, since
  1195  				// a.Offset is still relative to pseudo-SP.
  1196  				a.Reg = obj.REG_NONE
  1197  			}
  1198  			c.instoffset = c.autosize + a.Offset
  1199  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1200  				if immhalf(int32(c.instoffset)) {
  1201  					if immfloat(t) {
  1202  						return C_HFAUTO
  1203  					}
  1204  					return C_HAUTO
  1205  				}
  1206  
  1207  				if immfloat(t) {
  1208  					return C_FAUTO
  1209  				}
  1210  				return C_SAUTO
  1211  			}
  1212  
  1213  			return C_LAUTO
  1214  
  1215  		case obj.NAME_PARAM:
  1216  			if a.Reg == REGSP {
  1217  				// unset base register for better printing, since
  1218  				// a.Offset is still relative to pseudo-FP.
  1219  				a.Reg = obj.REG_NONE
  1220  			}
  1221  			c.instoffset = c.autosize + a.Offset + 4
  1222  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1223  				if immhalf(int32(c.instoffset)) {
  1224  					if immfloat(t) {
  1225  						return C_HFAUTO
  1226  					}
  1227  					return C_HAUTO
  1228  				}
  1229  
  1230  				if immfloat(t) {
  1231  					return C_FAUTO
  1232  				}
  1233  				return C_SAUTO
  1234  			}
  1235  
  1236  			return C_LAUTO
  1237  
  1238  		case obj.NAME_NONE:
  1239  			c.instoffset = a.Offset
  1240  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1241  				if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
  1242  					if immfloat(t) {
  1243  						return C_HFOREG
  1244  					}
  1245  					return C_HOREG
  1246  				}
  1247  
  1248  				if immfloat(t) {
  1249  					return C_FOREG /* n.b. that it will also satisfy immrot */
  1250  				}
  1251  				if immrot(uint32(c.instoffset)) != 0 {
  1252  					return C_SROREG
  1253  				}
  1254  				if immhalf(int32(c.instoffset)) {
  1255  					return C_HOREG
  1256  				}
  1257  				return C_SOREG
  1258  			}
  1259  
  1260  			if immrot(uint32(c.instoffset)) != 0 {
  1261  				return C_ROREG
  1262  			}
  1263  			return C_LOREG
  1264  		}
  1265  
  1266  		return C_GOK
  1267  
  1268  	case obj.TYPE_FCONST:
  1269  		if c.chipzero5(a.Val.(float64)) >= 0 {
  1270  			return C_ZFCON
  1271  		}
  1272  		if c.chipfloat5(a.Val.(float64)) >= 0 {
  1273  			return C_SFCON
  1274  		}
  1275  		return C_LFCON
  1276  
  1277  	case obj.TYPE_TEXTSIZE:
  1278  		return C_TEXTSIZE
  1279  
  1280  	case obj.TYPE_CONST,
  1281  		obj.TYPE_ADDR:
  1282  		switch a.Name {
  1283  		case obj.NAME_NONE:
  1284  			c.instoffset = a.Offset
  1285  			if a.Reg != 0 {
  1286  				return c.aconsize()
  1287  			}
  1288  
  1289  			if immrot(uint32(c.instoffset)) != 0 {
  1290  				return C_RCON
  1291  			}
  1292  			if immrot(^uint32(c.instoffset)) != 0 {
  1293  				return C_NCON
  1294  			}
  1295  			if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 {
  1296  				return C_SCON
  1297  			}
  1298  			if c.ctxt.Headtype != objabi.Hnacl {
  1299  				// Don't split instructions on NaCl. The validator is not
  1300  				// happy with it. See Issue 20595.
  1301  				if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
  1302  					return C_RCON2A
  1303  				}
  1304  				if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
  1305  					return C_RCON2S
  1306  				}
  1307  			}
  1308  			return C_LCON
  1309  
  1310  		case obj.NAME_EXTERN,
  1311  			obj.NAME_GOTREF,
  1312  			obj.NAME_STATIC:
  1313  			s := a.Sym
  1314  			if s == nil {
  1315  				break
  1316  			}
  1317  			c.instoffset = 0 // s.b. unused but just in case
  1318  			return C_LCONADDR
  1319  
  1320  		case obj.NAME_AUTO:
  1321  			if a.Reg == REGSP {
  1322  				// unset base register for better printing, since
  1323  				// a.Offset is still relative to pseudo-SP.
  1324  				a.Reg = obj.REG_NONE
  1325  			}
  1326  			c.instoffset = c.autosize + a.Offset
  1327  			return c.aconsize()
  1328  
  1329  		case obj.NAME_PARAM:
  1330  			if a.Reg == REGSP {
  1331  				// unset base register for better printing, since
  1332  				// a.Offset is still relative to pseudo-FP.
  1333  				a.Reg = obj.REG_NONE
  1334  			}
  1335  			c.instoffset = c.autosize + a.Offset + 4
  1336  			return c.aconsize()
  1337  		}
  1338  
  1339  		return C_GOK
  1340  
  1341  	case obj.TYPE_BRANCH:
  1342  		return C_SBRA
  1343  	}
  1344  
  1345  	return C_GOK
  1346  }
  1347  
  1348  func (c *ctxt5) aconsize() int {
  1349  	if immrot(uint32(c.instoffset)) != 0 {
  1350  		return C_RACON
  1351  	}
  1352  	if immrot(uint32(-c.instoffset)) != 0 {
  1353  		return C_RACON
  1354  	}
  1355  	return C_LACON
  1356  }
  1357  
  1358  func (c *ctxt5) oplook(p *obj.Prog) *Optab {
  1359  	a1 := int(p.Optab)
  1360  	if a1 != 0 {
  1361  		return &optab[a1-1]
  1362  	}
  1363  	a1 = int(p.From.Class)
  1364  	if a1 == 0 {
  1365  		a1 = c.aclass(&p.From) + 1
  1366  		p.From.Class = int8(a1)
  1367  	}
  1368  
  1369  	a1--
  1370  	a3 := int(p.To.Class)
  1371  	if a3 == 0 {
  1372  		a3 = c.aclass(&p.To) + 1
  1373  		p.To.Class = int8(a3)
  1374  	}
  1375  
  1376  	a3--
  1377  	a2 := C_NONE
  1378  	if p.Reg != 0 {
  1379  		switch {
  1380  		case REG_F0 <= p.Reg && p.Reg <= REG_F15:
  1381  			a2 = C_FREG
  1382  		case REG_R0 <= p.Reg && p.Reg <= REG_R15:
  1383  			a2 = C_REG
  1384  		default:
  1385  			c.ctxt.Diag("invalid register in %v", p)
  1386  		}
  1387  	}
  1388  
  1389  	// check illegal base register
  1390  	switch a1 {
  1391  	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
  1392  		if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
  1393  			c.ctxt.Diag("illegal base register: %v", p)
  1394  		}
  1395  	default:
  1396  	}
  1397  	switch a3 {
  1398  	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
  1399  		if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
  1400  			c.ctxt.Diag("illegal base register: %v", p)
  1401  		}
  1402  	default:
  1403  	}
  1404  
  1405  	// If current instruction has a .S suffix (flags update),
  1406  	// we must use the constant pool instead of splitting it.
  1407  	if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  1408  		a1 = C_LCON
  1409  	}
  1410  	if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  1411  		a3 = C_LCON
  1412  	}
  1413  
  1414  	if false { /*debug['O']*/
  1415  		fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
  1416  		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  1417  	}
  1418  
  1419  	ops := oprange[p.As&obj.AMask]
  1420  	c1 := &xcmp[a1]
  1421  	c3 := &xcmp[a3]
  1422  	for i := range ops {
  1423  		op := &ops[i]
  1424  		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
  1425  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1426  			return op
  1427  		}
  1428  	}
  1429  
  1430  	c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name)
  1431  	if ops == nil {
  1432  		ops = optab
  1433  	}
  1434  	return &ops[0]
  1435  }
  1436  
  1437  func cmp(a int, b int) bool {
  1438  	if a == b {
  1439  		return true
  1440  	}
  1441  	switch a {
  1442  	case C_LCON:
  1443  		if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
  1444  			return true
  1445  		}
  1446  
  1447  	case C_LACON:
  1448  		if b == C_RACON {
  1449  			return true
  1450  		}
  1451  
  1452  	case C_LFCON:
  1453  		if b == C_ZFCON || b == C_SFCON {
  1454  			return true
  1455  		}
  1456  
  1457  	case C_HFAUTO:
  1458  		return b == C_HAUTO || b == C_FAUTO
  1459  
  1460  	case C_FAUTO, C_HAUTO:
  1461  		return b == C_HFAUTO
  1462  
  1463  	case C_SAUTO:
  1464  		return cmp(C_HFAUTO, b)
  1465  
  1466  	case C_LAUTO:
  1467  		return cmp(C_SAUTO, b)
  1468  
  1469  	case C_HFOREG:
  1470  		return b == C_HOREG || b == C_FOREG
  1471  
  1472  	case C_FOREG, C_HOREG:
  1473  		return b == C_HFOREG
  1474  
  1475  	case C_SROREG:
  1476  		return cmp(C_SOREG, b) || cmp(C_ROREG, b)
  1477  
  1478  	case C_SOREG, C_ROREG:
  1479  		return b == C_SROREG || cmp(C_HFOREG, b)
  1480  
  1481  	case C_LOREG:
  1482  		return cmp(C_SROREG, b)
  1483  
  1484  	case C_LBRA:
  1485  		if b == C_SBRA {
  1486  			return true
  1487  		}
  1488  
  1489  	case C_HREG:
  1490  		return cmp(C_SP, b) || cmp(C_PC, b)
  1491  	}
  1492  
  1493  	return false
  1494  }
  1495  
  1496  type ocmp []Optab
  1497  
  1498  func (x ocmp) Len() int {
  1499  	return len(x)
  1500  }
  1501  
  1502  func (x ocmp) Swap(i, j int) {
  1503  	x[i], x[j] = x[j], x[i]
  1504  }
  1505  
  1506  func (x ocmp) Less(i, j int) bool {
  1507  	p1 := &x[i]
  1508  	p2 := &x[j]
  1509  	n := int(p1.as) - int(p2.as)
  1510  	if n != 0 {
  1511  		return n < 0
  1512  	}
  1513  	n = int(p1.a1) - int(p2.a1)
  1514  	if n != 0 {
  1515  		return n < 0
  1516  	}
  1517  	n = int(p1.a2) - int(p2.a2)
  1518  	if n != 0 {
  1519  		return n < 0
  1520  	}
  1521  	n = int(p1.a3) - int(p2.a3)
  1522  	if n != 0 {
  1523  		return n < 0
  1524  	}
  1525  	return false
  1526  }
  1527  
  1528  func opset(a, b0 obj.As) {
  1529  	oprange[a&obj.AMask] = oprange[b0]
  1530  }
  1531  
  1532  func buildop(ctxt *obj.Link) {
  1533  	if oprange[AAND&obj.AMask] != nil {
  1534  		// Already initialized; stop now.
  1535  		// This happens in the cmd/asm tests,
  1536  		// each of which re-initializes the arch.
  1537  		return
  1538  	}
  1539  
  1540  	deferreturn = ctxt.Lookup("runtime.deferreturn")
  1541  
  1542  	symdiv = ctxt.Lookup("runtime._div")
  1543  	symdivu = ctxt.Lookup("runtime._divu")
  1544  	symmod = ctxt.Lookup("runtime._mod")
  1545  	symmodu = ctxt.Lookup("runtime._modu")
  1546  
  1547  	var n int
  1548  
  1549  	for i := 0; i < C_GOK; i++ {
  1550  		for n = 0; n < C_GOK; n++ {
  1551  			if cmp(n, i) {
  1552  				xcmp[i][n] = true
  1553  			}
  1554  		}
  1555  	}
  1556  	for n = 0; optab[n].as != obj.AXXX; n++ {
  1557  		if optab[n].flag&LPCREL != 0 {
  1558  			if ctxt.Flag_shared {
  1559  				optab[n].size += int8(optab[n].pcrelsiz)
  1560  			} else {
  1561  				optab[n].flag &^= LPCREL
  1562  			}
  1563  		}
  1564  	}
  1565  
  1566  	sort.Sort(ocmp(optab[:n]))
  1567  	for i := 0; i < n; i++ {
  1568  		r := optab[i].as
  1569  		r0 := r & obj.AMask
  1570  		start := i
  1571  		for optab[i].as == r {
  1572  			i++
  1573  		}
  1574  		oprange[r0] = optab[start:i]
  1575  		i--
  1576  
  1577  		switch r {
  1578  		default:
  1579  			ctxt.Diag("unknown op in build: %v", r)
  1580  			log.Fatalf("bad code")
  1581  
  1582  		case AADD:
  1583  			opset(ASUB, r0)
  1584  			opset(ARSB, r0)
  1585  			opset(AADC, r0)
  1586  			opset(ASBC, r0)
  1587  			opset(ARSC, r0)
  1588  
  1589  		case AORR:
  1590  			opset(AEOR, r0)
  1591  			opset(ABIC, r0)
  1592  
  1593  		case ACMP:
  1594  			opset(ATEQ, r0)
  1595  			opset(ACMN, r0)
  1596  			opset(ATST, r0)
  1597  
  1598  		case AMVN:
  1599  			break
  1600  
  1601  		case ABEQ:
  1602  			opset(ABNE, r0)
  1603  			opset(ABCS, r0)
  1604  			opset(ABHS, r0)
  1605  			opset(ABCC, r0)
  1606  			opset(ABLO, r0)
  1607  			opset(ABMI, r0)
  1608  			opset(ABPL, r0)
  1609  			opset(ABVS, r0)
  1610  			opset(ABVC, r0)
  1611  			opset(ABHI, r0)
  1612  			opset(ABLS, r0)
  1613  			opset(ABGE, r0)
  1614  			opset(ABLT, r0)
  1615  			opset(ABGT, r0)
  1616  			opset(ABLE, r0)
  1617  
  1618  		case ASLL:
  1619  			opset(ASRL, r0)
  1620  			opset(ASRA, r0)
  1621  
  1622  		case AMUL:
  1623  			opset(AMULU, r0)
  1624  
  1625  		case ADIV:
  1626  			opset(AMOD, r0)
  1627  			opset(AMODU, r0)
  1628  			opset(ADIVU, r0)
  1629  
  1630  		case ADIVHW:
  1631  			opset(ADIVUHW, r0)
  1632  
  1633  		case AMOVW,
  1634  			AMOVB,
  1635  			AMOVBS,
  1636  			AMOVBU,
  1637  			AMOVH,
  1638  			AMOVHS,
  1639  			AMOVHU:
  1640  			break
  1641  
  1642  		case ASWPW:
  1643  			opset(ASWPBU, r0)
  1644  
  1645  		case AB,
  1646  			ABL,
  1647  			ABX,
  1648  			ABXRET,
  1649  			obj.ADUFFZERO,
  1650  			obj.ADUFFCOPY,
  1651  			ASWI,
  1652  			AWORD,
  1653  			AMOVM,
  1654  			ARFE,
  1655  			obj.ATEXT:
  1656  			break
  1657  
  1658  		case AADDF:
  1659  			opset(AADDD, r0)
  1660  			opset(ASUBF, r0)
  1661  			opset(ASUBD, r0)
  1662  			opset(AMULF, r0)
  1663  			opset(AMULD, r0)
  1664  			opset(ANMULF, r0)
  1665  			opset(ANMULD, r0)
  1666  			opset(AMULAF, r0)
  1667  			opset(AMULAD, r0)
  1668  			opset(AMULSF, r0)
  1669  			opset(AMULSD, r0)
  1670  			opset(ANMULAF, r0)
  1671  			opset(ANMULAD, r0)
  1672  			opset(ANMULSF, r0)
  1673  			opset(ANMULSD, r0)
  1674  			opset(AFMULAF, r0)
  1675  			opset(AFMULAD, r0)
  1676  			opset(AFMULSF, r0)
  1677  			opset(AFMULSD, r0)
  1678  			opset(AFNMULAF, r0)
  1679  			opset(AFNMULAD, r0)
  1680  			opset(AFNMULSF, r0)
  1681  			opset(AFNMULSD, r0)
  1682  			opset(ADIVF, r0)
  1683  			opset(ADIVD, r0)
  1684  
  1685  		case ANEGF:
  1686  			opset(ANEGD, r0)
  1687  			opset(ASQRTF, r0)
  1688  			opset(ASQRTD, r0)
  1689  			opset(AMOVFD, r0)
  1690  			opset(AMOVDF, r0)
  1691  			opset(AABSF, r0)
  1692  			opset(AABSD, r0)
  1693  
  1694  		case ACMPF:
  1695  			opset(ACMPD, r0)
  1696  
  1697  		case AMOVF:
  1698  			opset(AMOVD, r0)
  1699  
  1700  		case AMOVFW:
  1701  			opset(AMOVDW, r0)
  1702  
  1703  		case AMOVWF:
  1704  			opset(AMOVWD, r0)
  1705  
  1706  		case AMULL:
  1707  			opset(AMULAL, r0)
  1708  			opset(AMULLU, r0)
  1709  			opset(AMULALU, r0)
  1710  
  1711  		case AMULWT:
  1712  			opset(AMULWB, r0)
  1713  			opset(AMULBB, r0)
  1714  			opset(AMMUL, r0)
  1715  
  1716  		case AMULAWT:
  1717  			opset(AMULAWB, r0)
  1718  			opset(AMULABB, r0)
  1719  			opset(AMULA, r0)
  1720  			opset(AMULS, r0)
  1721  			opset(AMMULA, r0)
  1722  			opset(AMMULS, r0)
  1723  
  1724  		case ABFX:
  1725  			opset(ABFXU, r0)
  1726  
  1727  		case ACLZ:
  1728  			opset(AREV, r0)
  1729  			opset(AREV16, r0)
  1730  			opset(AREVSH, r0)
  1731  			opset(ARBIT, r0)
  1732  
  1733  		case AXTAB:
  1734  			opset(AXTAH, r0)
  1735  			opset(AXTABU, r0)
  1736  			opset(AXTAHU, r0)
  1737  
  1738  		case ALDREX,
  1739  			ASTREX,
  1740  			ALDREXD,
  1741  			ASTREXD,
  1742  			APLD,
  1743  			AAND,
  1744  			obj.AUNDEF,
  1745  			obj.AFUNCDATA,
  1746  			obj.APCDATA,
  1747  			obj.ANOP,
  1748  			ADATABUNDLE,
  1749  			ADATABUNDLEEND:
  1750  			break
  1751  		}
  1752  	}
  1753  }
  1754  
  1755  func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1756  	c.printp = p
  1757  	o1 := uint32(0)
  1758  	o2 := uint32(0)
  1759  	o3 := uint32(0)
  1760  	o4 := uint32(0)
  1761  	o5 := uint32(0)
  1762  	o6 := uint32(0)
  1763  	if false { /*debug['P']*/
  1764  		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  1765  	}
  1766  	switch o.type_ {
  1767  	default:
  1768  		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  1769  
  1770  	case 0: /* pseudo ops */
  1771  		if false { /*debug['G']*/
  1772  			fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
  1773  		}
  1774  
  1775  	case 1: /* op R,[R],R */
  1776  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1777  
  1778  		rf := int(p.From.Reg)
  1779  		rt := int(p.To.Reg)
  1780  		r := int(p.Reg)
  1781  		if p.To.Type == obj.TYPE_NONE {
  1782  			rt = 0
  1783  		}
  1784  		if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
  1785  			r = 0
  1786  		} else if r == 0 {
  1787  			r = rt
  1788  		}
  1789  		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1790  
  1791  	case 2: /* movbu $I,[R],R */
  1792  		c.aclass(&p.From)
  1793  
  1794  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1795  		o1 |= uint32(immrot(uint32(c.instoffset)))
  1796  		rt := int(p.To.Reg)
  1797  		r := int(p.Reg)
  1798  		if p.To.Type == obj.TYPE_NONE {
  1799  			rt = 0
  1800  		}
  1801  		if p.As == AMOVW || p.As == AMVN {
  1802  			r = 0
  1803  		} else if r == 0 {
  1804  			r = rt
  1805  		}
  1806  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1807  
  1808  	case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
  1809  		c.aclass(&p.From)
  1810  		r := int(p.Reg)
  1811  		rt := int(p.To.Reg)
  1812  		if r == 0 {
  1813  			r = rt
  1814  		}
  1815  		x, y := immrot2a(uint32(c.instoffset))
  1816  		var as2 obj.As
  1817  		switch p.As {
  1818  		case AADD, ASUB, AORR, AEOR, ABIC:
  1819  			as2 = p.As // ADD, SUB, ORR, EOR, BIC
  1820  		case ARSB:
  1821  			as2 = AADD // RSB -> RSB/ADD pair
  1822  		case AADC:
  1823  			as2 = AADD // ADC -> ADC/ADD pair
  1824  		case ASBC:
  1825  			as2 = ASUB // SBC -> SBC/SUB pair
  1826  		case ARSC:
  1827  			as2 = AADD // RSC -> RSC/ADD pair
  1828  		default:
  1829  			c.ctxt.Diag("unknown second op for %v", p)
  1830  		}
  1831  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1832  		o2 = c.oprrr(p, as2, int(p.Scond))
  1833  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1834  		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1835  		o1 |= x
  1836  		o2 |= y
  1837  
  1838  	case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
  1839  		c.aclass(&p.From)
  1840  		r := int(p.Reg)
  1841  		rt := int(p.To.Reg)
  1842  		if r == 0 {
  1843  			r = rt
  1844  		}
  1845  		y, x := immrot2s(uint32(c.instoffset))
  1846  		var as2 obj.As
  1847  		switch p.As {
  1848  		case AADD:
  1849  			as2 = ASUB // ADD -> ADD/SUB pair
  1850  		case ASUB:
  1851  			as2 = AADD // SUB -> SUB/ADD pair
  1852  		case ARSB:
  1853  			as2 = ASUB // RSB -> RSB/SUB pair
  1854  		case AADC:
  1855  			as2 = ASUB // ADC -> ADC/SUB pair
  1856  		case ASBC:
  1857  			as2 = AADD // SBC -> SBC/ADD pair
  1858  		case ARSC:
  1859  			as2 = ASUB // RSC -> RSC/SUB pair
  1860  		default:
  1861  			c.ctxt.Diag("unknown second op for %v", p)
  1862  		}
  1863  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1864  		o2 = c.oprrr(p, as2, int(p.Scond))
  1865  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1866  		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1867  		o1 |= y
  1868  		o2 |= x
  1869  
  1870  	case 3: /* add R<<[IR],[R],R */
  1871  		o1 = c.mov(p)
  1872  
  1873  	case 4: /* MOVW $off(R), R -> add $off,[R],R */
  1874  		c.aclass(&p.From)
  1875  		if c.instoffset < 0 {
  1876  			o1 = c.oprrr(p, ASUB, int(p.Scond))
  1877  			o1 |= uint32(immrot(uint32(-c.instoffset)))
  1878  		} else {
  1879  			o1 = c.oprrr(p, AADD, int(p.Scond))
  1880  			o1 |= uint32(immrot(uint32(c.instoffset)))
  1881  		}
  1882  		r := int(p.From.Reg)
  1883  		if r == 0 {
  1884  			r = int(o.param)
  1885  		}
  1886  		o1 |= (uint32(r) & 15) << 16
  1887  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1888  
  1889  	case 5: /* bra s */
  1890  		o1 = c.opbra(p, p.As, int(p.Scond))
  1891  
  1892  		v := int32(-8)
  1893  		if p.To.Sym != nil {
  1894  			rel := obj.Addrel(c.cursym)
  1895  			rel.Off = int32(c.pc)
  1896  			rel.Siz = 4
  1897  			rel.Sym = p.To.Sym
  1898  			v += int32(p.To.Offset)
  1899  			rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
  1900  			rel.Type = objabi.R_CALLARM
  1901  			break
  1902  		}
  1903  
  1904  		if p.Pcond != nil {
  1905  			v = int32((p.Pcond.Pc - c.pc) - 8)
  1906  		}
  1907  		o1 |= (uint32(v) >> 2) & 0xffffff
  1908  
  1909  	case 6: /* b ,O(R) -> add $O,R,PC */
  1910  		c.aclass(&p.To)
  1911  
  1912  		o1 = c.oprrr(p, AADD, int(p.Scond))
  1913  		o1 |= uint32(immrot(uint32(c.instoffset)))
  1914  		o1 |= (uint32(p.To.Reg) & 15) << 16
  1915  		o1 |= (REGPC & 15) << 12
  1916  
  1917  	case 7: /* bl (R) -> blx R */
  1918  		c.aclass(&p.To)
  1919  
  1920  		if c.instoffset != 0 {
  1921  			c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
  1922  		}
  1923  		o1 = c.oprrr(p, ABL, int(p.Scond))
  1924  		o1 |= (uint32(p.To.Reg) & 15) << 0
  1925  		rel := obj.Addrel(c.cursym)
  1926  		rel.Off = int32(c.pc)
  1927  		rel.Siz = 0
  1928  		rel.Type = objabi.R_CALLIND
  1929  
  1930  	case 8: /* sll $c,[R],R -> mov (R<<$c),R */
  1931  		c.aclass(&p.From)
  1932  
  1933  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1934  		r := int(p.Reg)
  1935  		if r == 0 {
  1936  			r = int(p.To.Reg)
  1937  		}
  1938  		o1 |= (uint32(r) & 15) << 0
  1939  		o1 |= uint32((c.instoffset & 31) << 7)
  1940  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1941  
  1942  	case 9: /* sll R,[R],R -> mov (R<<R),R */
  1943  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1944  
  1945  		r := int(p.Reg)
  1946  		if r == 0 {
  1947  			r = int(p.To.Reg)
  1948  		}
  1949  		o1 |= (uint32(r) & 15) << 0
  1950  		o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
  1951  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1952  
  1953  	case 10: /* swi [$con] */
  1954  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1955  
  1956  		if p.To.Type != obj.TYPE_NONE {
  1957  			c.aclass(&p.To)
  1958  			o1 |= uint32(c.instoffset & 0xffffff)
  1959  		}
  1960  
  1961  	case 11: /* word */
  1962  		c.aclass(&p.To)
  1963  
  1964  		o1 = uint32(c.instoffset)
  1965  		if p.To.Sym != nil {
  1966  			// This case happens with words generated
  1967  			// in the PC stream as part of the literal pool (c.pool).
  1968  			rel := obj.Addrel(c.cursym)
  1969  
  1970  			rel.Off = int32(c.pc)
  1971  			rel.Siz = 4
  1972  			rel.Sym = p.To.Sym
  1973  			rel.Add = p.To.Offset
  1974  
  1975  			if c.ctxt.Flag_shared {
  1976  				if p.To.Name == obj.NAME_GOTREF {
  1977  					rel.Type = objabi.R_GOTPCREL
  1978  				} else {
  1979  					rel.Type = objabi.R_PCREL
  1980  				}
  1981  				rel.Add += c.pc - p.Rel.Pc - 8
  1982  			} else {
  1983  				rel.Type = objabi.R_ADDR
  1984  			}
  1985  			o1 = 0
  1986  		}
  1987  
  1988  	case 12: /* movw $lcon, reg */
  1989  		if o.a1 == C_SCON {
  1990  			o1 = c.omvs(p, &p.From, int(p.To.Reg))
  1991  		} else if p.As == AMVN {
  1992  			o1 = c.omvr(p, &p.From, int(p.To.Reg))
  1993  		} else {
  1994  			o1 = c.omvl(p, &p.From, int(p.To.Reg))
  1995  		}
  1996  
  1997  		if o.flag&LPCREL != 0 {
  1998  			o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
  1999  		}
  2000  
  2001  	case 13: /* op $lcon, [R], R */
  2002  		if o.a1 == C_SCON {
  2003  			o1 = c.omvs(p, &p.From, REGTMP)
  2004  		} else {
  2005  			o1 = c.omvl(p, &p.From, REGTMP)
  2006  		}
  2007  
  2008  		if o1 == 0 {
  2009  			break
  2010  		}
  2011  		o2 = c.oprrr(p, p.As, int(p.Scond))
  2012  		o2 |= REGTMP & 15
  2013  		r := int(p.Reg)
  2014  		if p.As == AMOVW || p.As == AMVN {
  2015  			r = 0
  2016  		} else if r == 0 {
  2017  			r = int(p.To.Reg)
  2018  		}
  2019  		o2 |= (uint32(r) & 15) << 16
  2020  		if p.To.Type != obj.TYPE_NONE {
  2021  			o2 |= (uint32(p.To.Reg) & 15) << 12
  2022  		}
  2023  
  2024  	case 14: /* movb/movbu/movh/movhu R,R */
  2025  		o1 = c.oprrr(p, ASLL, int(p.Scond))
  2026  
  2027  		if p.As == AMOVBU || p.As == AMOVHU {
  2028  			o2 = c.oprrr(p, ASRL, int(p.Scond))
  2029  		} else {
  2030  			o2 = c.oprrr(p, ASRA, int(p.Scond))
  2031  		}
  2032  
  2033  		r := int(p.To.Reg)
  2034  		o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
  2035  		o2 |= uint32(r)&15 | (uint32(r)&15)<<12
  2036  		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  2037  			o1 |= 24 << 7
  2038  			o2 |= 24 << 7
  2039  		} else {
  2040  			o1 |= 16 << 7
  2041  			o2 |= 16 << 7
  2042  		}
  2043  
  2044  	case 15: /* mul r,[r,]r */
  2045  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2046  
  2047  		rf := int(p.From.Reg)
  2048  		rt := int(p.To.Reg)
  2049  		r := int(p.Reg)
  2050  		if r == 0 {
  2051  			r = rt
  2052  		}
  2053  		if rt == r {
  2054  			r = rf
  2055  			rf = rt
  2056  		}
  2057  
  2058  		if false {
  2059  			if rt == r || rf == REGPC&15 || r == REGPC&15 || rt == REGPC&15 {
  2060  				c.ctxt.Diag("%v: bad registers in MUL", p)
  2061  			}
  2062  		}
  2063  
  2064  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  2065  
  2066  	case 16: /* div r,[r,]r */
  2067  		o1 = 0xf << 28
  2068  
  2069  		o2 = 0
  2070  
  2071  	case 17:
  2072  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2073  		rf := int(p.From.Reg)
  2074  		rt := int(p.To.Reg)
  2075  		rt2 := int(p.To.Offset)
  2076  		r := int(p.Reg)
  2077  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
  2078  
  2079  	case 18: /* BFX/BFXU */
  2080  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2081  		rt := int(p.To.Reg)
  2082  		r := int(p.Reg)
  2083  		if r == 0 {
  2084  			r = rt
  2085  		}
  2086  		if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
  2087  			c.ctxt.Diag("%v: missing or wrong LSB", p)
  2088  			break
  2089  		}
  2090  		lsb := p.GetFrom3().Offset
  2091  		width := p.From.Offset
  2092  		if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 31 {
  2093  			c.ctxt.Diag("%v: wrong width or LSB", p)
  2094  		}
  2095  		o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
  2096  
  2097  	case 20: /* mov/movb/movbu R,O(R) */
  2098  		c.aclass(&p.To)
  2099  
  2100  		r := int(p.To.Reg)
  2101  		if r == 0 {
  2102  			r = int(o.param)
  2103  		}
  2104  		o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  2105  
  2106  	case 21: /* mov/movbu O(R),R -> lr */
  2107  		c.aclass(&p.From)
  2108  
  2109  		r := int(p.From.Reg)
  2110  		if r == 0 {
  2111  			r = int(o.param)
  2112  		}
  2113  		o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  2114  		if p.As != AMOVW {
  2115  			o1 |= 1 << 22
  2116  		}
  2117  
  2118  	case 22: /* XTAB R@>i, [R], R */
  2119  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2120  		switch p.From.Offset &^ 0xf {
  2121  		// only 0/8/16/24 bits rotation is accepted
  2122  		case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
  2123  			o1 |= uint32(p.From.Offset) & 0xc0f
  2124  		default:
  2125  			c.ctxt.Diag("illegal shift: %v", p)
  2126  		}
  2127  		rt := p.To.Reg
  2128  		r := p.Reg
  2129  		if r == 0 {
  2130  			r = rt
  2131  		}
  2132  		o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
  2133  
  2134  	case 23: /* MOVW/MOVB/MOVH R@>i, R */
  2135  		switch p.As {
  2136  		case AMOVW:
  2137  			o1 = c.mov(p)
  2138  		case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
  2139  			o1 = c.movxt(p)
  2140  		default:
  2141  			c.ctxt.Diag("illegal combination: %v", p)
  2142  		}
  2143  
  2144  	case 30: /* mov/movb/movbu R,L(R) */
  2145  		o1 = c.omvl(p, &p.To, REGTMP)
  2146  
  2147  		if o1 == 0 {
  2148  			break
  2149  		}
  2150  		r := int(p.To.Reg)
  2151  		if r == 0 {
  2152  			r = int(o.param)
  2153  		}
  2154  		o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  2155  		if p.As != AMOVW {
  2156  			o2 |= 1 << 22
  2157  		}
  2158  
  2159  	case 31: /* mov/movbu L(R),R -> lr[b] */
  2160  		o1 = c.omvl(p, &p.From, REGTMP)
  2161  
  2162  		if o1 == 0 {
  2163  			break
  2164  		}
  2165  		r := int(p.From.Reg)
  2166  		if r == 0 {
  2167  			r = int(o.param)
  2168  		}
  2169  		o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  2170  		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  2171  			o2 |= 1 << 22
  2172  		}
  2173  
  2174  	case 34: /* mov $lacon,R */
  2175  		o1 = c.omvl(p, &p.From, REGTMP)
  2176  
  2177  		if o1 == 0 {
  2178  			break
  2179  		}
  2180  
  2181  		o2 = c.oprrr(p, AADD, int(p.Scond))
  2182  		o2 |= REGTMP & 15
  2183  		r := int(p.From.Reg)
  2184  		if r == 0 {
  2185  			r = int(o.param)
  2186  		}
  2187  		o2 |= (uint32(r) & 15) << 16
  2188  		if p.To.Type != obj.TYPE_NONE {
  2189  			o2 |= (uint32(p.To.Reg) & 15) << 12
  2190  		}
  2191  
  2192  	case 35: /* mov PSR,R */
  2193  		o1 = 2<<23 | 0xf<<16 | 0<<0
  2194  
  2195  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2196  		o1 |= (uint32(p.From.Reg) & 1) << 22
  2197  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2198  
  2199  	case 36: /* mov R,PSR */
  2200  		o1 = 2<<23 | 0x2cf<<12 | 0<<4
  2201  
  2202  		if p.Scond&C_FBIT != 0 {
  2203  			o1 ^= 0x010 << 12
  2204  		}
  2205  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2206  		o1 |= (uint32(p.To.Reg) & 1) << 22
  2207  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2208  
  2209  	case 37: /* mov $con,PSR */
  2210  		c.aclass(&p.From)
  2211  
  2212  		o1 = 2<<23 | 0x2cf<<12 | 0<<4
  2213  		if p.Scond&C_FBIT != 0 {
  2214  			o1 ^= 0x010 << 12
  2215  		}
  2216  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2217  		o1 |= uint32(immrot(uint32(c.instoffset)))
  2218  		o1 |= (uint32(p.To.Reg) & 1) << 22
  2219  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2220  
  2221  	case 38, 39:
  2222  		switch o.type_ {
  2223  		case 38: /* movm $con,oreg -> stm */
  2224  			o1 = 0x4 << 25
  2225  
  2226  			o1 |= uint32(p.From.Offset & 0xffff)
  2227  			o1 |= (uint32(p.To.Reg) & 15) << 16
  2228  			c.aclass(&p.To)
  2229  
  2230  		case 39: /* movm oreg,$con -> ldm */
  2231  			o1 = 0x4<<25 | 1<<20
  2232  
  2233  			o1 |= uint32(p.To.Offset & 0xffff)
  2234  			o1 |= (uint32(p.From.Reg) & 15) << 16
  2235  			c.aclass(&p.From)
  2236  		}
  2237  
  2238  		if c.instoffset != 0 {
  2239  			c.ctxt.Diag("offset must be zero in MOVM; %v", p)
  2240  		}
  2241  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2242  		if p.Scond&C_PBIT != 0 {
  2243  			o1 |= 1 << 24
  2244  		}
  2245  		if p.Scond&C_UBIT != 0 {
  2246  			o1 |= 1 << 23
  2247  		}
  2248  		if p.Scond&C_WBIT != 0 {
  2249  			o1 |= 1 << 21
  2250  		}
  2251  
  2252  	case 40: /* swp oreg,reg,reg */
  2253  		c.aclass(&p.From)
  2254  
  2255  		if c.instoffset != 0 {
  2256  			c.ctxt.Diag("offset must be zero in SWP")
  2257  		}
  2258  		o1 = 0x2<<23 | 0x9<<4
  2259  		if p.As != ASWPW {
  2260  			o1 |= 1 << 22
  2261  		}
  2262  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2263  		o1 |= (uint32(p.Reg) & 15) << 0
  2264  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2265  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2266  
  2267  	case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
  2268  		o1 = 0xe8fd8000
  2269  
  2270  	case 50: /* floating point store */
  2271  		v := c.regoff(&p.To)
  2272  
  2273  		r := int(p.To.Reg)
  2274  		if r == 0 {
  2275  			r = int(o.param)
  2276  		}
  2277  		o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
  2278  
  2279  	case 51: /* floating point load */
  2280  		v := c.regoff(&p.From)
  2281  
  2282  		r := int(p.From.Reg)
  2283  		if r == 0 {
  2284  			r = int(o.param)
  2285  		}
  2286  		o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
  2287  
  2288  	case 52: /* floating point store, int32 offset UGLY */
  2289  		o1 = c.omvl(p, &p.To, REGTMP)
  2290  
  2291  		if o1 == 0 {
  2292  			break
  2293  		}
  2294  		r := int(p.To.Reg)
  2295  		if r == 0 {
  2296  			r = int(o.param)
  2297  		}
  2298  		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  2299  		o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  2300  
  2301  	case 53: /* floating point load, int32 offset UGLY */
  2302  		o1 = c.omvl(p, &p.From, REGTMP)
  2303  
  2304  		if o1 == 0 {
  2305  			break
  2306  		}
  2307  		r := int(p.From.Reg)
  2308  		if r == 0 {
  2309  			r = int(o.param)
  2310  		}
  2311  		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  2312  		o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  2313  
  2314  	case 54: /* floating point arith */
  2315  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2316  
  2317  		rf := int(p.From.Reg)
  2318  		rt := int(p.To.Reg)
  2319  		r := int(p.Reg)
  2320  		if r == 0 {
  2321  			switch p.As {
  2322  			case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
  2323  				AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
  2324  				c.ctxt.Diag("illegal combination: %v", p)
  2325  			default:
  2326  				r = rt
  2327  			}
  2328  		}
  2329  
  2330  		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2331  
  2332  	case 55: /* negf freg, freg */
  2333  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2334  
  2335  		rf := int(p.From.Reg)
  2336  		rt := int(p.To.Reg)
  2337  
  2338  		o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
  2339  
  2340  	case 56: /* move to FP[CS]R */
  2341  		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
  2342  
  2343  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2344  
  2345  	case 57: /* move from FP[CS]R */
  2346  		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
  2347  
  2348  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2349  
  2350  	case 58: /* movbu R,R */
  2351  		o1 = c.oprrr(p, AAND, int(p.Scond))
  2352  
  2353  		o1 |= uint32(immrot(0xff))
  2354  		rt := int(p.To.Reg)
  2355  		r := int(p.From.Reg)
  2356  		if p.To.Type == obj.TYPE_NONE {
  2357  			rt = 0
  2358  		}
  2359  		if r == 0 {
  2360  			r = rt
  2361  		}
  2362  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2363  
  2364  	case 59: /* movw/bu R<<I(R),R -> ldr indexed */
  2365  		if p.From.Reg == 0 {
  2366  			c.ctxt.Diag("source operand is not a memory address: %v", p)
  2367  			break
  2368  		}
  2369  		if p.From.Offset&(1<<4) != 0 {
  2370  			c.ctxt.Diag("bad shift in LDR")
  2371  			break
  2372  		}
  2373  		o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  2374  		if p.As == AMOVBU {
  2375  			o1 |= 1 << 22
  2376  		}
  2377  
  2378  	case 60: /* movb R(R),R -> ldrsb indexed */
  2379  		if p.From.Reg == 0 {
  2380  			c.ctxt.Diag("source operand is not a memory address: %v", p)
  2381  			break
  2382  		}
  2383  		if p.From.Offset&(^0xf) != 0 {
  2384  			c.ctxt.Diag("bad shift: %v", p)
  2385  			break
  2386  		}
  2387  		o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  2388  		switch p.As {
  2389  		case AMOVB, AMOVBS:
  2390  			o1 ^= 1<<5 | 1<<6
  2391  		case AMOVH, AMOVHS:
  2392  			o1 ^= 1 << 6
  2393  		default:
  2394  		}
  2395  		if p.Scond&C_UBIT != 0 {
  2396  			o1 &^= 1 << 23
  2397  		}
  2398  
  2399  	case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
  2400  		if p.To.Reg == 0 {
  2401  			c.ctxt.Diag("MOV to shifter operand")
  2402  		}
  2403  		o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
  2404  		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  2405  			o1 |= 1 << 22
  2406  		}
  2407  
  2408  	case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */
  2409  		if p.To.Reg == 0 {
  2410  			c.ctxt.Diag("MOV to shifter operand")
  2411  		}
  2412  		if p.To.Offset&(^0xf) != 0 {
  2413  			c.ctxt.Diag("bad shift: %v", p)
  2414  		}
  2415  		o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
  2416  		o1 ^= 1 << 20
  2417  		if p.Scond&C_UBIT != 0 {
  2418  			o1 &^= 1 << 23
  2419  		}
  2420  
  2421  		/* reloc ops */
  2422  	case 64: /* mov/movb/movbu R,addr */
  2423  		o1 = c.omvl(p, &p.To, REGTMP)
  2424  
  2425  		if o1 == 0 {
  2426  			break
  2427  		}
  2428  		o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
  2429  		if o.flag&LPCREL != 0 {
  2430  			o3 = o2
  2431  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2432  		}
  2433  
  2434  	case 65: /* mov/movbu addr,R */
  2435  		o1 = c.omvl(p, &p.From, REGTMP)
  2436  
  2437  		if o1 == 0 {
  2438  			break
  2439  		}
  2440  		o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  2441  		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  2442  			o2 |= 1 << 22
  2443  		}
  2444  		if o.flag&LPCREL != 0 {
  2445  			o3 = o2
  2446  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2447  		}
  2448  
  2449  	case 101: /* movw tlsvar,R, local exec*/
  2450  		if p.Scond&C_SCOND != C_SCOND_NONE {
  2451  			c.ctxt.Diag("conditional tls")
  2452  		}
  2453  		o1 = c.omvl(p, &p.From, int(p.To.Reg))
  2454  
  2455  	case 102: /* movw tlsvar,R, initial exec*/
  2456  		if p.Scond&C_SCOND != C_SCOND_NONE {
  2457  			c.ctxt.Diag("conditional tls")
  2458  		}
  2459  		o1 = c.omvl(p, &p.From, int(p.To.Reg))
  2460  		o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
  2461  
  2462  	case 103: /* word tlsvar, local exec */
  2463  		if p.To.Sym == nil {
  2464  			c.ctxt.Diag("nil sym in tls %v", p)
  2465  		}
  2466  		if p.To.Offset != 0 {
  2467  			c.ctxt.Diag("offset against tls var in %v", p)
  2468  		}
  2469  		// This case happens with words generated in the PC stream as part of
  2470  		// the literal c.pool.
  2471  		rel := obj.Addrel(c.cursym)
  2472  
  2473  		rel.Off = int32(c.pc)
  2474  		rel.Siz = 4
  2475  		rel.Sym = p.To.Sym
  2476  		rel.Type = objabi.R_TLS_LE
  2477  		o1 = 0
  2478  
  2479  	case 104: /* word tlsvar, initial exec */
  2480  		if p.To.Sym == nil {
  2481  			c.ctxt.Diag("nil sym in tls %v", p)
  2482  		}
  2483  		if p.To.Offset != 0 {
  2484  			c.ctxt.Diag("offset against tls var in %v", p)
  2485  		}
  2486  		rel := obj.Addrel(c.cursym)
  2487  		rel.Off = int32(c.pc)
  2488  		rel.Siz = 4
  2489  		rel.Sym = p.To.Sym
  2490  		rel.Type = objabi.R_TLS_IE
  2491  		rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
  2492  
  2493  	case 68: /* floating point store -> ADDR */
  2494  		o1 = c.omvl(p, &p.To, REGTMP)
  2495  
  2496  		if o1 == 0 {
  2497  			break
  2498  		}
  2499  		o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  2500  		if o.flag&LPCREL != 0 {
  2501  			o3 = o2
  2502  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2503  		}
  2504  
  2505  	case 69: /* floating point load <- ADDR */
  2506  		o1 = c.omvl(p, &p.From, REGTMP)
  2507  
  2508  		if o1 == 0 {
  2509  			break
  2510  		}
  2511  		o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  2512  		if o.flag&LPCREL != 0 {
  2513  			o3 = o2
  2514  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2515  		}
  2516  
  2517  		/* ArmV4 ops: */
  2518  	case 70: /* movh/movhu R,O(R) -> strh */
  2519  		c.aclass(&p.To)
  2520  
  2521  		r := int(p.To.Reg)
  2522  		if r == 0 {
  2523  			r = int(o.param)
  2524  		}
  2525  		o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  2526  
  2527  	case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
  2528  		c.aclass(&p.From)
  2529  
  2530  		r := int(p.From.Reg)
  2531  		if r == 0 {
  2532  			r = int(o.param)
  2533  		}
  2534  		o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  2535  		if p.As == AMOVB || p.As == AMOVBS {
  2536  			o1 ^= 1<<5 | 1<<6
  2537  		} else if p.As == AMOVH || p.As == AMOVHS {
  2538  			o1 ^= (1 << 6)
  2539  		}
  2540  
  2541  	case 72: /* movh/movhu R,L(R) -> strh */
  2542  		o1 = c.omvl(p, &p.To, REGTMP)
  2543  
  2544  		if o1 == 0 {
  2545  			break
  2546  		}
  2547  		r := int(p.To.Reg)
  2548  		if r == 0 {
  2549  			r = int(o.param)
  2550  		}
  2551  		o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  2552  
  2553  	case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
  2554  		o1 = c.omvl(p, &p.From, REGTMP)
  2555  
  2556  		if o1 == 0 {
  2557  			break
  2558  		}
  2559  		r := int(p.From.Reg)
  2560  		if r == 0 {
  2561  			r = int(o.param)
  2562  		}
  2563  		o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  2564  		if p.As == AMOVB || p.As == AMOVBS {
  2565  			o2 ^= 1<<5 | 1<<6
  2566  		} else if p.As == AMOVH || p.As == AMOVHS {
  2567  			o2 ^= (1 << 6)
  2568  		}
  2569  
  2570  	case 74: /* bx $I */
  2571  		c.ctxt.Diag("ABX $I")
  2572  
  2573  	case 75: /* bx O(R) */
  2574  		c.aclass(&p.To)
  2575  
  2576  		if c.instoffset != 0 {
  2577  			c.ctxt.Diag("non-zero offset in ABX")
  2578  		}
  2579  
  2580  		/*
  2581  			o1 = 	c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12);	// mov PC, LR
  2582  			o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0);		// BX R
  2583  		*/
  2584  		// p->to.reg may be REGLINK
  2585  		o1 = c.oprrr(p, AADD, int(p.Scond))
  2586  
  2587  		o1 |= uint32(immrot(uint32(c.instoffset)))
  2588  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2589  		o1 |= (REGTMP & 15) << 12
  2590  		o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
  2591  		o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15            // BX Rtmp
  2592  
  2593  	case 76: /* bx O(R) when returning from fn*/
  2594  		c.ctxt.Diag("ABXRET")
  2595  
  2596  	case 77: /* ldrex oreg,reg */
  2597  		c.aclass(&p.From)
  2598  
  2599  		if c.instoffset != 0 {
  2600  			c.ctxt.Diag("offset must be zero in LDREX")
  2601  		}
  2602  		o1 = 0x19<<20 | 0xf9f
  2603  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2604  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2605  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2606  
  2607  	case 78: /* strex reg,oreg,reg */
  2608  		c.aclass(&p.From)
  2609  
  2610  		if c.instoffset != 0 {
  2611  			c.ctxt.Diag("offset must be zero in STREX")
  2612  		}
  2613  		o1 = 0x18<<20 | 0xf90
  2614  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2615  		o1 |= (uint32(p.Reg) & 15) << 0
  2616  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2617  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2618  
  2619  	case 80: /* fmov zfcon,freg */
  2620  		if p.As == AMOVD {
  2621  			o1 = 0xeeb00b00 // VMOV imm 64
  2622  			o2 = c.oprrr(p, ASUBD, int(p.Scond))
  2623  		} else {
  2624  			o1 = 0x0eb00a00 // VMOV imm 32
  2625  			o2 = c.oprrr(p, ASUBF, int(p.Scond))
  2626  		}
  2627  
  2628  		v := int32(0x70) // 1.0
  2629  		r := (int(p.To.Reg) & 15) << 0
  2630  
  2631  		// movf $1.0, r
  2632  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2633  
  2634  		o1 |= (uint32(r) & 15) << 12
  2635  		o1 |= (uint32(v) & 0xf) << 0
  2636  		o1 |= (uint32(v) & 0xf0) << 12
  2637  
  2638  		// subf r,r,r
  2639  		o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
  2640  
  2641  	case 81: /* fmov sfcon,freg */
  2642  		o1 = 0x0eb00a00 // VMOV imm 32
  2643  		if p.As == AMOVD {
  2644  			o1 = 0xeeb00b00 // VMOV imm 64
  2645  		}
  2646  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2647  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2648  		v := int32(c.chipfloat5(p.From.Val.(float64)))
  2649  		o1 |= (uint32(v) & 0xf) << 0
  2650  		o1 |= (uint32(v) & 0xf0) << 12
  2651  
  2652  	case 82: /* fcmp freg,freg, */
  2653  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2654  
  2655  		o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
  2656  		o2 = 0x0ef1fa10 // VMRS R15
  2657  		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2658  
  2659  	case 83: /* fcmp freg,, */
  2660  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2661  
  2662  		o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
  2663  		o2 = 0x0ef1fa10 // VMRS R15
  2664  		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2665  
  2666  	case 84: /* movfw freg,freg - truncate float-to-fix */
  2667  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2668  
  2669  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2670  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2671  
  2672  	case 85: /* movwf freg,freg - fix-to-float */
  2673  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2674  
  2675  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2676  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2677  
  2678  		// macro for movfw freg,FTMP; movw FTMP,reg
  2679  	case 86: /* movfw freg,reg - truncate float-to-fix */
  2680  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2681  
  2682  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2683  		o1 |= (FREGTMP & 15) << 12
  2684  		o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2685  		o2 |= (FREGTMP & 15) << 16
  2686  		o2 |= (uint32(p.To.Reg) & 15) << 12
  2687  
  2688  		// macro for movw reg,FTMP; movwf FTMP,freg
  2689  	case 87: /* movwf reg,freg - fix-to-float */
  2690  		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2691  
  2692  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2693  		o1 |= (FREGTMP & 15) << 16
  2694  		o2 = c.oprrr(p, p.As, int(p.Scond))
  2695  		o2 |= (FREGTMP & 15) << 0
  2696  		o2 |= (uint32(p.To.Reg) & 15) << 12
  2697  
  2698  	case 88: /* movw reg,freg  */
  2699  		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2700  
  2701  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2702  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2703  
  2704  	case 89: /* movw freg,reg  */
  2705  		o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2706  
  2707  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2708  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2709  
  2710  	case 91: /* ldrexd oreg,reg */
  2711  		c.aclass(&p.From)
  2712  
  2713  		if c.instoffset != 0 {
  2714  			c.ctxt.Diag("offset must be zero in LDREX")
  2715  		}
  2716  		o1 = 0x1b<<20 | 0xf9f
  2717  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2718  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2719  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2720  
  2721  	case 92: /* strexd reg,oreg,reg */
  2722  		c.aclass(&p.From)
  2723  
  2724  		if c.instoffset != 0 {
  2725  			c.ctxt.Diag("offset must be zero in STREX")
  2726  		}
  2727  		o1 = 0x1a<<20 | 0xf90
  2728  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2729  		o1 |= (uint32(p.Reg) & 15) << 0
  2730  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2731  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2732  
  2733  	case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
  2734  		o1 = c.omvl(p, &p.From, REGTMP)
  2735  
  2736  		if o1 == 0 {
  2737  			break
  2738  		}
  2739  		o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  2740  		if p.As == AMOVB || p.As == AMOVBS {
  2741  			o2 ^= 1<<5 | 1<<6
  2742  		} else if p.As == AMOVH || p.As == AMOVHS {
  2743  			o2 ^= (1 << 6)
  2744  		}
  2745  		if o.flag&LPCREL != 0 {
  2746  			o3 = o2
  2747  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2748  		}
  2749  
  2750  	case 94: /* movh/movhu R,addr -> strh */
  2751  		o1 = c.omvl(p, &p.To, REGTMP)
  2752  
  2753  		if o1 == 0 {
  2754  			break
  2755  		}
  2756  		o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
  2757  		if o.flag&LPCREL != 0 {
  2758  			o3 = o2
  2759  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2760  		}
  2761  
  2762  	case 95: /* PLD off(reg) */
  2763  		o1 = 0xf5d0f000
  2764  
  2765  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2766  		if p.From.Offset < 0 {
  2767  			o1 &^= (1 << 23)
  2768  			o1 |= uint32((-p.From.Offset) & 0xfff)
  2769  		} else {
  2770  			o1 |= uint32(p.From.Offset & 0xfff)
  2771  		}
  2772  
  2773  	// This is supposed to be something that stops execution.
  2774  	// It's not supposed to be reached, ever, but if it is, we'd
  2775  	// like to be able to tell how we got there. Assemble as
  2776  	// 0xf7fabcfd which is guaranteed to raise undefined instruction
  2777  	// exception.
  2778  	case 96: /* UNDEF */
  2779  		o1 = 0xf7fabcfd
  2780  
  2781  	case 97: /* CLZ Rm, Rd */
  2782  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2783  
  2784  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2785  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2786  
  2787  	case 98: /* MULW{T,B} Rs, Rm, Rd */
  2788  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2789  
  2790  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2791  		o1 |= (uint32(p.From.Reg) & 15) << 8
  2792  		o1 |= (uint32(p.Reg) & 15) << 0
  2793  
  2794  	case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
  2795  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2796  
  2797  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2798  		o1 |= (uint32(p.From.Reg) & 15) << 8
  2799  		o1 |= (uint32(p.Reg) & 15) << 0
  2800  		o1 |= uint32((p.To.Offset & 15) << 12)
  2801  
  2802  	// DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
  2803  	// DATABUNDLEEND: zero width alignment marker
  2804  	case 100:
  2805  		if p.As == ADATABUNDLE {
  2806  			o1 = 0xe125be70
  2807  		}
  2808  
  2809  	case 105: /* divhw r,[r,]r */
  2810  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2811  		rf := int(p.From.Reg)
  2812  		rt := int(p.To.Reg)
  2813  		r := int(p.Reg)
  2814  		if r == 0 {
  2815  			r = rt
  2816  		}
  2817  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  2818  	}
  2819  
  2820  	out[0] = o1
  2821  	out[1] = o2
  2822  	out[2] = o3
  2823  	out[3] = o4
  2824  	out[4] = o5
  2825  	out[5] = o6
  2826  	return
  2827  }
  2828  
  2829  func (c *ctxt5) movxt(p *obj.Prog) uint32 {
  2830  	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2831  	switch p.As {
  2832  	case AMOVB, AMOVBS:
  2833  		o1 |= 0x6af<<16 | 0x7<<4
  2834  	case AMOVH, AMOVHS:
  2835  		o1 |= 0x6bf<<16 | 0x7<<4
  2836  	case AMOVBU:
  2837  		o1 |= 0x6ef<<16 | 0x7<<4
  2838  	case AMOVHU:
  2839  		o1 |= 0x6ff<<16 | 0x7<<4
  2840  	default:
  2841  		c.ctxt.Diag("illegal combination: %v", p)
  2842  	}
  2843  	switch p.From.Offset &^ 0xf {
  2844  	// only 0/8/16/24 bits rotation is accepted
  2845  	case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
  2846  		o1 |= uint32(p.From.Offset) & 0xc0f
  2847  	default:
  2848  		c.ctxt.Diag("illegal shift: %v", p)
  2849  	}
  2850  	o1 |= (uint32(p.To.Reg) & 15) << 12
  2851  	return o1
  2852  }
  2853  
  2854  func (c *ctxt5) mov(p *obj.Prog) uint32 {
  2855  	c.aclass(&p.From)
  2856  	o1 := c.oprrr(p, p.As, int(p.Scond))
  2857  	o1 |= uint32(p.From.Offset)
  2858  	rt := int(p.To.Reg)
  2859  	if p.To.Type == obj.TYPE_NONE {
  2860  		rt = 0
  2861  	}
  2862  	r := int(p.Reg)
  2863  	if p.As == AMOVW || p.As == AMVN {
  2864  		r = 0
  2865  	} else if r == 0 {
  2866  		r = rt
  2867  	}
  2868  	o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2869  	return o1
  2870  }
  2871  
  2872  func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
  2873  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2874  	if sc&C_SBIT != 0 {
  2875  		o |= 1 << 20
  2876  	}
  2877  	switch a {
  2878  	case ADIVHW:
  2879  		return o | 0x71<<20 | 0xf<<12 | 0x1<<4
  2880  	case ADIVUHW:
  2881  		return o | 0x73<<20 | 0xf<<12 | 0x1<<4
  2882  	case AMMUL:
  2883  		return o | 0x75<<20 | 0xf<<12 | 0x1<<4
  2884  	case AMULS:
  2885  		return o | 0x6<<20 | 0x9<<4
  2886  	case AMMULA:
  2887  		return o | 0x75<<20 | 0x1<<4
  2888  	case AMMULS:
  2889  		return o | 0x75<<20 | 0xd<<4
  2890  	case AMULU, AMUL:
  2891  		return o | 0x0<<21 | 0x9<<4
  2892  	case AMULA:
  2893  		return o | 0x1<<21 | 0x9<<4
  2894  	case AMULLU:
  2895  		return o | 0x4<<21 | 0x9<<4
  2896  	case AMULL:
  2897  		return o | 0x6<<21 | 0x9<<4
  2898  	case AMULALU:
  2899  		return o | 0x5<<21 | 0x9<<4
  2900  	case AMULAL:
  2901  		return o | 0x7<<21 | 0x9<<4
  2902  	case AAND:
  2903  		return o | 0x0<<21
  2904  	case AEOR:
  2905  		return o | 0x1<<21
  2906  	case ASUB:
  2907  		return o | 0x2<<21
  2908  	case ARSB:
  2909  		return o | 0x3<<21
  2910  	case AADD:
  2911  		return o | 0x4<<21
  2912  	case AADC:
  2913  		return o | 0x5<<21
  2914  	case ASBC:
  2915  		return o | 0x6<<21
  2916  	case ARSC:
  2917  		return o | 0x7<<21
  2918  	case ATST:
  2919  		return o | 0x8<<21 | 1<<20
  2920  	case ATEQ:
  2921  		return o | 0x9<<21 | 1<<20
  2922  	case ACMP:
  2923  		return o | 0xa<<21 | 1<<20
  2924  	case ACMN:
  2925  		return o | 0xb<<21 | 1<<20
  2926  	case AORR:
  2927  		return o | 0xc<<21
  2928  
  2929  	case AMOVB, AMOVH, AMOVW:
  2930  		if sc&(C_PBIT|C_WBIT) != 0 {
  2931  			c.ctxt.Diag("invalid .P/.W suffix: %v", p)
  2932  		}
  2933  		return o | 0xd<<21
  2934  	case ABIC:
  2935  		return o | 0xe<<21
  2936  	case AMVN:
  2937  		return o | 0xf<<21
  2938  	case ASLL:
  2939  		return o | 0xd<<21 | 0<<5
  2940  	case ASRL:
  2941  		return o | 0xd<<21 | 1<<5
  2942  	case ASRA:
  2943  		return o | 0xd<<21 | 2<<5
  2944  	case ASWI:
  2945  		return o | 0xf<<24
  2946  
  2947  	case AADDD:
  2948  		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
  2949  	case AADDF:
  2950  		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
  2951  	case ASUBD:
  2952  		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
  2953  	case ASUBF:
  2954  		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
  2955  	case AMULD:
  2956  		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
  2957  	case AMULF:
  2958  		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
  2959  	case ANMULD:
  2960  		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
  2961  	case ANMULF:
  2962  		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
  2963  	case AMULAD:
  2964  		return o | 0xe<<24 | 0xb<<8
  2965  	case AMULAF:
  2966  		return o | 0xe<<24 | 0xa<<8
  2967  	case AMULSD:
  2968  		return o | 0xe<<24 | 0xb<<8 | 0x4<<4
  2969  	case AMULSF:
  2970  		return o | 0xe<<24 | 0xa<<8 | 0x4<<4
  2971  	case ANMULAD:
  2972  		return o | 0xe<<24 | 0x1<<20 | 0xb<<8
  2973  	case ANMULAF:
  2974  		return o | 0xe<<24 | 0x1<<20 | 0xa<<8
  2975  	case ANMULSD:
  2976  		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
  2977  	case ANMULSF:
  2978  		return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
  2979  	case AFMULAD:
  2980  		return o | 0xe<<24 | 0xa<<20 | 0xb<<8
  2981  	case AFMULAF:
  2982  		return o | 0xe<<24 | 0xa<<20 | 0xa<<8
  2983  	case AFMULSD:
  2984  		return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
  2985  	case AFMULSF:
  2986  		return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
  2987  	case AFNMULAD:
  2988  		return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
  2989  	case AFNMULAF:
  2990  		return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
  2991  	case AFNMULSD:
  2992  		return o | 0xe<<24 | 0x9<<20 | 0xb<<8
  2993  	case AFNMULSF:
  2994  		return o | 0xe<<24 | 0x9<<20 | 0xa<<8
  2995  	case ADIVD:
  2996  		return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
  2997  	case ADIVF:
  2998  		return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
  2999  	case ASQRTD:
  3000  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
  3001  	case ASQRTF:
  3002  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
  3003  	case AABSD:
  3004  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
  3005  	case AABSF:
  3006  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
  3007  	case ANEGD:
  3008  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
  3009  	case ANEGF:
  3010  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
  3011  	case ACMPD:
  3012  		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
  3013  	case ACMPF:
  3014  		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
  3015  
  3016  	case AMOVF:
  3017  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
  3018  	case AMOVD:
  3019  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
  3020  
  3021  	case AMOVDF:
  3022  		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
  3023  	case AMOVFD:
  3024  		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
  3025  
  3026  	case AMOVWF:
  3027  		if sc&C_UBIT == 0 {
  3028  			o |= 1 << 7 /* signed */
  3029  		}
  3030  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
  3031  
  3032  	case AMOVWD:
  3033  		if sc&C_UBIT == 0 {
  3034  			o |= 1 << 7 /* signed */
  3035  		}
  3036  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
  3037  
  3038  	case AMOVFW:
  3039  		if sc&C_UBIT == 0 {
  3040  			o |= 1 << 16 /* signed */
  3041  		}
  3042  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
  3043  
  3044  	case AMOVDW:
  3045  		if sc&C_UBIT == 0 {
  3046  			o |= 1 << 16 /* signed */
  3047  		}
  3048  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
  3049  
  3050  	case -AMOVWF: // copy WtoF
  3051  		return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
  3052  
  3053  	case -AMOVFW: // copy FtoW
  3054  		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
  3055  
  3056  	case -ACMP: // cmp imm
  3057  		return o | 0x3<<24 | 0x5<<20
  3058  
  3059  	case ABFX:
  3060  		return o | 0x3d<<21 | 0x5<<4
  3061  
  3062  	case ABFXU:
  3063  		return o | 0x3f<<21 | 0x5<<4
  3064  
  3065  	case AXTAB:
  3066  		return o | 0x6a<<20 | 0x7<<4
  3067  
  3068  	case AXTAH:
  3069  		return o | 0x6b<<20 | 0x7<<4
  3070  
  3071  	case AXTABU:
  3072  		return o | 0x6e<<20 | 0x7<<4
  3073  
  3074  	case AXTAHU:
  3075  		return o | 0x6f<<20 | 0x7<<4
  3076  
  3077  		// CLZ doesn't support .nil
  3078  	case ACLZ:
  3079  		return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
  3080  
  3081  	case AREV:
  3082  		return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
  3083  
  3084  	case AREV16:
  3085  		return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
  3086  
  3087  	case AREVSH:
  3088  		return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
  3089  
  3090  	case ARBIT:
  3091  		return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
  3092  
  3093  	case AMULWT:
  3094  		return o&(0xf<<28) | 0x12<<20 | 0xe<<4
  3095  
  3096  	case AMULWB:
  3097  		return o&(0xf<<28) | 0x12<<20 | 0xa<<4
  3098  
  3099  	case AMULBB:
  3100  		return o&(0xf<<28) | 0x16<<20 | 0x8<<4
  3101  
  3102  	case AMULAWT:
  3103  		return o&(0xf<<28) | 0x12<<20 | 0xc<<4
  3104  
  3105  	case AMULAWB:
  3106  		return o&(0xf<<28) | 0x12<<20 | 0x8<<4
  3107  
  3108  	case AMULABB:
  3109  		return o&(0xf<<28) | 0x10<<20 | 0x8<<4
  3110  
  3111  	case ABL: // BLX REG
  3112  		return o&(0xf<<28) | 0x12fff3<<4
  3113  	}
  3114  
  3115  	c.ctxt.Diag("%v: bad rrr %d", p, a)
  3116  	return 0
  3117  }
  3118  
  3119  func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
  3120  	sc &= C_SCOND
  3121  	sc ^= C_SCOND_XOR
  3122  	if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
  3123  		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
  3124  	}
  3125  	if sc != 0xe {
  3126  		c.ctxt.Diag("%v: .COND on bcond instruction", p)
  3127  	}
  3128  	switch a {
  3129  	case ABEQ:
  3130  		return 0x0<<28 | 0x5<<25
  3131  	case ABNE:
  3132  		return 0x1<<28 | 0x5<<25
  3133  	case ABCS:
  3134  		return 0x2<<28 | 0x5<<25
  3135  	case ABHS:
  3136  		return 0x2<<28 | 0x5<<25
  3137  	case ABCC:
  3138  		return 0x3<<28 | 0x5<<25
  3139  	case ABLO:
  3140  		return 0x3<<28 | 0x5<<25
  3141  	case ABMI:
  3142  		return 0x4<<28 | 0x5<<25
  3143  	case ABPL:
  3144  		return 0x5<<28 | 0x5<<25
  3145  	case ABVS:
  3146  		return 0x6<<28 | 0x5<<25
  3147  	case ABVC:
  3148  		return 0x7<<28 | 0x5<<25
  3149  	case ABHI:
  3150  		return 0x8<<28 | 0x5<<25
  3151  	case ABLS:
  3152  		return 0x9<<28 | 0x5<<25
  3153  	case ABGE:
  3154  		return 0xa<<28 | 0x5<<25
  3155  	case ABLT:
  3156  		return 0xb<<28 | 0x5<<25
  3157  	case ABGT:
  3158  		return 0xc<<28 | 0x5<<25
  3159  	case ABLE:
  3160  		return 0xd<<28 | 0x5<<25
  3161  	case AB:
  3162  		return 0xe<<28 | 0x5<<25
  3163  	}
  3164  
  3165  	c.ctxt.Diag("%v: bad bra %v", p, a)
  3166  	return 0
  3167  }
  3168  
  3169  func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
  3170  	if sc&C_SBIT != 0 {
  3171  		c.ctxt.Diag(".nil on LDR/STR instruction")
  3172  	}
  3173  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  3174  	if sc&C_PBIT == 0 {
  3175  		o |= 1 << 24
  3176  	}
  3177  	if sc&C_UBIT == 0 {
  3178  		o |= 1 << 23
  3179  	}
  3180  	if sc&C_WBIT != 0 {
  3181  		o |= 1 << 21
  3182  	}
  3183  	o |= 1<<26 | 1<<20
  3184  	if v < 0 {
  3185  		if sc&C_UBIT != 0 {
  3186  			c.ctxt.Diag(".U on neg offset")
  3187  		}
  3188  		v = -v
  3189  		o ^= 1 << 23
  3190  	}
  3191  
  3192  	if v >= 1<<12 || v < 0 {
  3193  		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  3194  	}
  3195  	o |= uint32(v)
  3196  	o |= (uint32(b) & 15) << 16
  3197  	o |= (uint32(r) & 15) << 12
  3198  	return o
  3199  }
  3200  
  3201  func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
  3202  	if sc&C_SBIT != 0 {
  3203  		c.ctxt.Diag(".nil on LDRH/STRH instruction")
  3204  	}
  3205  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  3206  	if sc&C_PBIT == 0 {
  3207  		o |= 1 << 24
  3208  	}
  3209  	if sc&C_WBIT != 0 {
  3210  		o |= 1 << 21
  3211  	}
  3212  	o |= 1<<23 | 1<<20 | 0xb<<4
  3213  	if v < 0 {
  3214  		v = -v
  3215  		o ^= 1 << 23
  3216  	}
  3217  
  3218  	if v >= 1<<8 || v < 0 {
  3219  		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  3220  	}
  3221  	o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
  3222  	o |= (uint32(b) & 15) << 16
  3223  	o |= (uint32(r) & 15) << 12
  3224  	return o
  3225  }
  3226  
  3227  func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
  3228  	o := c.olr(v, b, r, sc) ^ (1 << 20)
  3229  	if a != AMOVW {
  3230  		o |= 1 << 22
  3231  	}
  3232  	return o
  3233  }
  3234  
  3235  func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
  3236  	o := c.olhr(v, b, r, sc) ^ (1 << 20)
  3237  	return o
  3238  }
  3239  
  3240  func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
  3241  	return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
  3242  }
  3243  
  3244  func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
  3245  	return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
  3246  }
  3247  
  3248  func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
  3249  	return c.olr(int32(i), b, r, sc) ^ (1 << 25)
  3250  }
  3251  
  3252  func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
  3253  	return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
  3254  }
  3255  
  3256  func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
  3257  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  3258  	if sc&C_PBIT == 0 {
  3259  		o |= 1 << 24
  3260  	}
  3261  	if sc&C_WBIT != 0 {
  3262  		o |= 1 << 21
  3263  	}
  3264  	o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
  3265  	if v < 0 {
  3266  		v = -v
  3267  		o ^= 1 << 23
  3268  	}
  3269  
  3270  	if v&3 != 0 {
  3271  		c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
  3272  	} else if v >= 1<<10 || v < 0 {
  3273  		c.ctxt.Diag("literal span too large: %d\n%v", v, p)
  3274  	}
  3275  	o |= (uint32(v) >> 2) & 0xFF
  3276  	o |= (uint32(b) & 15) << 16
  3277  	o |= (uint32(r) & 15) << 12
  3278  
  3279  	switch a {
  3280  	default:
  3281  		c.ctxt.Diag("bad fst %v", a)
  3282  		fallthrough
  3283  
  3284  	case AMOVD:
  3285  		o |= 1 << 8
  3286  		fallthrough
  3287  
  3288  	case AMOVF:
  3289  		break
  3290  	}
  3291  
  3292  	return o
  3293  }
  3294  
  3295  // MOVW $"lower 16-bit", Reg
  3296  func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  3297  	var o1 uint32
  3298  	o1 = ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  3299  	o1 |= 0x30 << 20
  3300  	o1 |= (uint32(dr) & 15) << 12
  3301  	o1 |= uint32(a.Offset) & 0x0fff
  3302  	o1 |= (uint32(a.Offset) & 0xf000) << 4
  3303  	return o1
  3304  }
  3305  
  3306  // MVN $C_NCON, Reg -> MOVW $C_RCON, Reg
  3307  func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  3308  	o1 := c.oprrr(p, AMOVW, int(p.Scond))
  3309  	o1 |= (uint32(dr) & 15) << 12
  3310  	v := immrot(^uint32(a.Offset))
  3311  	if v == 0 {
  3312  		c.ctxt.Diag("%v: missing literal", p)
  3313  		return 0
  3314  	}
  3315  	o1 |= uint32(v)
  3316  	return o1
  3317  }
  3318  
  3319  func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  3320  	var o1 uint32
  3321  	if p.Pcond == nil {
  3322  		c.aclass(a)
  3323  		v := immrot(^uint32(c.instoffset))
  3324  		if v == 0 {
  3325  			c.ctxt.Diag("%v: missing literal", p)
  3326  			return 0
  3327  		}
  3328  
  3329  		o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
  3330  		o1 |= uint32(v)
  3331  		o1 |= (uint32(dr) & 15) << 12
  3332  	} else {
  3333  		v := int32(p.Pcond.Pc - p.Pc - 8)
  3334  		o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
  3335  	}
  3336  
  3337  	return o1
  3338  }
  3339  
  3340  func (c *ctxt5) chipzero5(e float64) int {
  3341  	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  3342  	if objabi.GOARM < 7 || math.Float64bits(e) != 0 {
  3343  		return -1
  3344  	}
  3345  	return 0
  3346  }
  3347  
  3348  func (c *ctxt5) chipfloat5(e float64) int {
  3349  	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  3350  	if objabi.GOARM < 7 {
  3351  		return -1
  3352  	}
  3353  
  3354  	ei := math.Float64bits(e)
  3355  	l := uint32(ei)
  3356  	h := uint32(ei >> 32)
  3357  
  3358  	if l != 0 || h&0xffff != 0 {
  3359  		return -1
  3360  	}
  3361  	h1 := h & 0x7fc00000
  3362  	if h1 != 0x40000000 && h1 != 0x3fc00000 {
  3363  		return -1
  3364  	}
  3365  	n := 0
  3366  
  3367  	// sign bit (a)
  3368  	if h&0x80000000 != 0 {
  3369  		n |= 1 << 7
  3370  	}
  3371  
  3372  	// exp sign bit (b)
  3373  	if h1 == 0x3fc00000 {
  3374  		n |= 1 << 6
  3375  	}
  3376  
  3377  	// rest of exp and mantissa (cd-efgh)
  3378  	n |= int((h >> 16) & 0x3f)
  3379  
  3380  	//print("match %.8lux %.8lux %d\n", l, h, n);
  3381  	return n
  3382  }
  3383  
  3384  func nocache(p *obj.Prog) {
  3385  	p.Optab = 0
  3386  	p.From.Class = 0
  3387  	if p.GetFrom3() != nil {
  3388  		p.GetFrom3().Class = 0
  3389  	}
  3390  	p.To.Class = 0
  3391  }