github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/obj/arm/asm5.go (about)

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