github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/obj/arm/asm5.go (about)

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