Source file src/cmd/internal/obj/arm/asm5.go

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

View as plain text