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