github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/cmd/internal/obj/arm/asm5.go (about)

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