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

View as plain text