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