...

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

Documentation: cmd/internal/obj/arm

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

View as plain text