Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/internal/obj/arm

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

View as plain text