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