...

Source file src/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go

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

View as plain text