github.com/filosottile/go@v0.0.0-20170906193555-dbed9972d994/src/cmd/internal/obj/arm/asm5.go (about)

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