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