github.com/ActiveState/go@v0.0.0-20170614201249-0b81c023a722/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  			c.instoffset = c.autosize + a.Offset
  1171  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1172  				if immhalf(int32(c.instoffset)) {
  1173  					if immfloat(t) {
  1174  						return C_HFAUTO
  1175  					}
  1176  					return C_HAUTO
  1177  				}
  1178  
  1179  				if immfloat(t) {
  1180  					return C_FAUTO
  1181  				}
  1182  				return C_SAUTO
  1183  			}
  1184  
  1185  			return C_LAUTO
  1186  
  1187  		case obj.NAME_PARAM:
  1188  			c.instoffset = c.autosize + a.Offset + 4
  1189  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1190  				if immhalf(int32(c.instoffset)) {
  1191  					if immfloat(t) {
  1192  						return C_HFAUTO
  1193  					}
  1194  					return C_HAUTO
  1195  				}
  1196  
  1197  				if immfloat(t) {
  1198  					return C_FAUTO
  1199  				}
  1200  				return C_SAUTO
  1201  			}
  1202  
  1203  			return C_LAUTO
  1204  
  1205  		case obj.NAME_NONE:
  1206  			c.instoffset = a.Offset
  1207  			if t := immaddr(int32(c.instoffset)); t != 0 {
  1208  				if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
  1209  					if immfloat(t) {
  1210  						return C_HFOREG
  1211  					}
  1212  					return C_HOREG
  1213  				}
  1214  
  1215  				if immfloat(t) {
  1216  					return C_FOREG /* n.b. that it will also satisfy immrot */
  1217  				}
  1218  				if immrot(uint32(c.instoffset)) != 0 {
  1219  					return C_SROREG
  1220  				}
  1221  				if immhalf(int32(c.instoffset)) {
  1222  					return C_HOREG
  1223  				}
  1224  				return C_SOREG
  1225  			}
  1226  
  1227  			if immrot(uint32(c.instoffset)) != 0 {
  1228  				return C_ROREG
  1229  			}
  1230  			return C_LOREG
  1231  		}
  1232  
  1233  		return C_GOK
  1234  
  1235  	case obj.TYPE_FCONST:
  1236  		if c.chipzero5(a.Val.(float64)) >= 0 {
  1237  			return C_ZFCON
  1238  		}
  1239  		if c.chipfloat5(a.Val.(float64)) >= 0 {
  1240  			return C_SFCON
  1241  		}
  1242  		return C_LFCON
  1243  
  1244  	case obj.TYPE_TEXTSIZE:
  1245  		return C_TEXTSIZE
  1246  
  1247  	case obj.TYPE_CONST,
  1248  		obj.TYPE_ADDR:
  1249  		switch a.Name {
  1250  		case obj.NAME_NONE:
  1251  			c.instoffset = a.Offset
  1252  			if a.Reg != 0 {
  1253  				return c.aconsize()
  1254  			}
  1255  
  1256  			if immrot(uint32(c.instoffset)) != 0 {
  1257  				return C_RCON
  1258  			}
  1259  			if immrot(^uint32(c.instoffset)) != 0 {
  1260  				return C_NCON
  1261  			}
  1262  			if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 {
  1263  				return C_SCON
  1264  			}
  1265  			if c.ctxt.Headtype != objabi.Hnacl {
  1266  				// Don't split instructions on NaCl. The validator is not
  1267  				// happy with it. See Issue 20595.
  1268  				if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
  1269  					return C_RCON2A
  1270  				}
  1271  				if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
  1272  					return C_RCON2S
  1273  				}
  1274  			}
  1275  			return C_LCON
  1276  
  1277  		case obj.NAME_EXTERN,
  1278  			obj.NAME_GOTREF,
  1279  			obj.NAME_STATIC:
  1280  			s := a.Sym
  1281  			if s == nil {
  1282  				break
  1283  			}
  1284  			c.instoffset = 0 // s.b. unused but just in case
  1285  			return C_LCONADDR
  1286  
  1287  		case obj.NAME_AUTO:
  1288  			c.instoffset = c.autosize + a.Offset
  1289  			return c.aconsize()
  1290  
  1291  		case obj.NAME_PARAM:
  1292  			c.instoffset = c.autosize + a.Offset + 4
  1293  			return c.aconsize()
  1294  		}
  1295  
  1296  		return C_GOK
  1297  
  1298  	case obj.TYPE_BRANCH:
  1299  		return C_SBRA
  1300  	}
  1301  
  1302  	return C_GOK
  1303  }
  1304  
  1305  func (c *ctxt5) aconsize() int {
  1306  	if immrot(uint32(c.instoffset)) != 0 {
  1307  		return C_RACON
  1308  	}
  1309  	if immrot(uint32(-c.instoffset)) != 0 {
  1310  		return C_RACON
  1311  	}
  1312  	return C_LACON
  1313  }
  1314  
  1315  func (c *ctxt5) oplook(p *obj.Prog) *Optab {
  1316  	a1 := int(p.Optab)
  1317  	if a1 != 0 {
  1318  		return &optab[a1-1]
  1319  	}
  1320  	a1 = int(p.From.Class)
  1321  	if a1 == 0 {
  1322  		a1 = c.aclass(&p.From) + 1
  1323  		p.From.Class = int8(a1)
  1324  	}
  1325  
  1326  	a1--
  1327  	a3 := int(p.To.Class)
  1328  	if a3 == 0 {
  1329  		a3 = c.aclass(&p.To) + 1
  1330  		p.To.Class = int8(a3)
  1331  	}
  1332  
  1333  	a3--
  1334  	a2 := C_NONE
  1335  	if p.Reg != 0 {
  1336  		switch {
  1337  		case REG_F0 <= p.Reg && p.Reg <= REG_F15:
  1338  			a2 = C_FREG
  1339  		case REG_R0 <= p.Reg && p.Reg <= REG_R15:
  1340  			a2 = C_REG
  1341  		default:
  1342  			c.ctxt.Diag("invalid register in %v", p)
  1343  		}
  1344  	}
  1345  
  1346  	// If current instruction has a .S suffix (flags update),
  1347  	// we must use the constant pool instead of splitting it.
  1348  	if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  1349  		a1 = C_LCON
  1350  	}
  1351  	if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  1352  		a3 = C_LCON
  1353  	}
  1354  
  1355  	if false { /*debug['O']*/
  1356  		fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
  1357  		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  1358  	}
  1359  
  1360  	ops := oprange[p.As&obj.AMask]
  1361  	c1 := &xcmp[a1]
  1362  	c3 := &xcmp[a3]
  1363  	for i := range ops {
  1364  		op := &ops[i]
  1365  		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
  1366  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1367  			return op
  1368  		}
  1369  	}
  1370  
  1371  	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)
  1372  	if ops == nil {
  1373  		ops = optab
  1374  	}
  1375  	return &ops[0]
  1376  }
  1377  
  1378  func cmp(a int, b int) bool {
  1379  	if a == b {
  1380  		return true
  1381  	}
  1382  	switch a {
  1383  	case C_LCON:
  1384  		if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
  1385  			return true
  1386  		}
  1387  
  1388  	case C_LACON:
  1389  		if b == C_RACON {
  1390  			return true
  1391  		}
  1392  
  1393  	case C_LFCON:
  1394  		if b == C_ZFCON || b == C_SFCON {
  1395  			return true
  1396  		}
  1397  
  1398  	case C_HFAUTO:
  1399  		return b == C_HAUTO || b == C_FAUTO
  1400  
  1401  	case C_FAUTO, C_HAUTO:
  1402  		return b == C_HFAUTO
  1403  
  1404  	case C_SAUTO:
  1405  		return cmp(C_HFAUTO, b)
  1406  
  1407  	case C_LAUTO:
  1408  		return cmp(C_SAUTO, b)
  1409  
  1410  	case C_HFOREG:
  1411  		return b == C_HOREG || b == C_FOREG
  1412  
  1413  	case C_FOREG, C_HOREG:
  1414  		return b == C_HFOREG
  1415  
  1416  	case C_SROREG:
  1417  		return cmp(C_SOREG, b) || cmp(C_ROREG, b)
  1418  
  1419  	case C_SOREG, C_ROREG:
  1420  		return b == C_SROREG || cmp(C_HFOREG, b)
  1421  
  1422  	case C_LOREG:
  1423  		return cmp(C_SROREG, b)
  1424  
  1425  	case C_LBRA:
  1426  		if b == C_SBRA {
  1427  			return true
  1428  		}
  1429  
  1430  	case C_HREG:
  1431  		return cmp(C_SP, b) || cmp(C_PC, b)
  1432  	}
  1433  
  1434  	return false
  1435  }
  1436  
  1437  type ocmp []Optab
  1438  
  1439  func (x ocmp) Len() int {
  1440  	return len(x)
  1441  }
  1442  
  1443  func (x ocmp) Swap(i, j int) {
  1444  	x[i], x[j] = x[j], x[i]
  1445  }
  1446  
  1447  func (x ocmp) Less(i, j int) bool {
  1448  	p1 := &x[i]
  1449  	p2 := &x[j]
  1450  	n := int(p1.as) - int(p2.as)
  1451  	if n != 0 {
  1452  		return n < 0
  1453  	}
  1454  	n = int(p1.a1) - int(p2.a1)
  1455  	if n != 0 {
  1456  		return n < 0
  1457  	}
  1458  	n = int(p1.a2) - int(p2.a2)
  1459  	if n != 0 {
  1460  		return n < 0
  1461  	}
  1462  	n = int(p1.a3) - int(p2.a3)
  1463  	if n != 0 {
  1464  		return n < 0
  1465  	}
  1466  	return false
  1467  }
  1468  
  1469  func opset(a, b0 obj.As) {
  1470  	oprange[a&obj.AMask] = oprange[b0]
  1471  }
  1472  
  1473  func buildop(ctxt *obj.Link) {
  1474  	if oprange[AAND&obj.AMask] != nil {
  1475  		// Already initialized; stop now.
  1476  		// This happens in the cmd/asm tests,
  1477  		// each of which re-initializes the arch.
  1478  		return
  1479  	}
  1480  
  1481  	deferreturn = ctxt.Lookup("runtime.deferreturn")
  1482  
  1483  	symdiv = ctxt.Lookup("_div")
  1484  	symdivu = ctxt.Lookup("_divu")
  1485  	symmod = ctxt.Lookup("_mod")
  1486  	symmodu = ctxt.Lookup("_modu")
  1487  
  1488  	var n int
  1489  
  1490  	for i := 0; i < C_GOK; i++ {
  1491  		for n = 0; n < C_GOK; n++ {
  1492  			if cmp(n, i) {
  1493  				xcmp[i][n] = true
  1494  			}
  1495  		}
  1496  	}
  1497  	for n = 0; optab[n].as != obj.AXXX; n++ {
  1498  		if optab[n].flag&LPCREL != 0 {
  1499  			if ctxt.Flag_shared {
  1500  				optab[n].size += int8(optab[n].pcrelsiz)
  1501  			} else {
  1502  				optab[n].flag &^= LPCREL
  1503  			}
  1504  		}
  1505  	}
  1506  
  1507  	sort.Sort(ocmp(optab[:n]))
  1508  	for i := 0; i < n; i++ {
  1509  		r := optab[i].as
  1510  		r0 := r & obj.AMask
  1511  		start := i
  1512  		for optab[i].as == r {
  1513  			i++
  1514  		}
  1515  		oprange[r0] = optab[start:i]
  1516  		i--
  1517  
  1518  		switch r {
  1519  		default:
  1520  			ctxt.Diag("unknown op in build: %v", r)
  1521  			log.Fatalf("bad code")
  1522  
  1523  		case AADD:
  1524  			opset(ASUB, r0)
  1525  			opset(ARSB, r0)
  1526  			opset(AADC, r0)
  1527  			opset(ASBC, r0)
  1528  			opset(ARSC, r0)
  1529  
  1530  		case AORR:
  1531  			opset(AEOR, r0)
  1532  			opset(ABIC, r0)
  1533  
  1534  		case ACMP:
  1535  			opset(ATEQ, r0)
  1536  			opset(ACMN, r0)
  1537  			opset(ATST, r0)
  1538  
  1539  		case AMVN:
  1540  			break
  1541  
  1542  		case ABEQ:
  1543  			opset(ABNE, r0)
  1544  			opset(ABCS, r0)
  1545  			opset(ABHS, r0)
  1546  			opset(ABCC, r0)
  1547  			opset(ABLO, r0)
  1548  			opset(ABMI, r0)
  1549  			opset(ABPL, r0)
  1550  			opset(ABVS, r0)
  1551  			opset(ABVC, r0)
  1552  			opset(ABHI, r0)
  1553  			opset(ABLS, r0)
  1554  			opset(ABGE, r0)
  1555  			opset(ABLT, r0)
  1556  			opset(ABGT, r0)
  1557  			opset(ABLE, r0)
  1558  
  1559  		case ASLL:
  1560  			opset(ASRL, r0)
  1561  			opset(ASRA, r0)
  1562  
  1563  		case AMUL:
  1564  			opset(AMULU, r0)
  1565  
  1566  		case ADIV:
  1567  			opset(AMOD, r0)
  1568  			opset(AMODU, r0)
  1569  			opset(ADIVU, r0)
  1570  
  1571  		case ADIVHW:
  1572  			opset(ADIVUHW, r0)
  1573  
  1574  		case AMOVW,
  1575  			AMOVB,
  1576  			AMOVBS,
  1577  			AMOVBU,
  1578  			AMOVH,
  1579  			AMOVHS,
  1580  			AMOVHU:
  1581  			break
  1582  
  1583  		case ASWPW:
  1584  			opset(ASWPBU, r0)
  1585  
  1586  		case AB,
  1587  			ABL,
  1588  			ABX,
  1589  			ABXRET,
  1590  			obj.ADUFFZERO,
  1591  			obj.ADUFFCOPY,
  1592  			ASWI,
  1593  			AWORD,
  1594  			AMOVM,
  1595  			ARFE,
  1596  			obj.ATEXT:
  1597  			break
  1598  
  1599  		case AADDF:
  1600  			opset(AADDD, r0)
  1601  			opset(ASUBF, r0)
  1602  			opset(ASUBD, r0)
  1603  			opset(AMULF, r0)
  1604  			opset(AMULD, r0)
  1605  			opset(ADIVF, r0)
  1606  			opset(ADIVD, r0)
  1607  
  1608  		case ANEGF:
  1609  			opset(ANEGD, r0)
  1610  			opset(ASQRTF, r0)
  1611  			opset(ASQRTD, r0)
  1612  			opset(AMOVFD, r0)
  1613  			opset(AMOVDF, r0)
  1614  			opset(AABSF, r0)
  1615  			opset(AABSD, r0)
  1616  
  1617  		case ACMPF:
  1618  			opset(ACMPD, r0)
  1619  
  1620  		case AMOVF:
  1621  			opset(AMOVD, r0)
  1622  
  1623  		case AMOVFW:
  1624  			opset(AMOVDW, r0)
  1625  
  1626  		case AMOVWF:
  1627  			opset(AMOVWD, r0)
  1628  
  1629  		case AMULL:
  1630  			opset(AMULAL, r0)
  1631  			opset(AMULLU, r0)
  1632  			opset(AMULALU, r0)
  1633  
  1634  		case AMULWT:
  1635  			opset(AMULWB, r0)
  1636  			opset(AMULBB, r0)
  1637  			opset(AMMUL, r0)
  1638  
  1639  		case AMULAWT:
  1640  			opset(AMULAWB, r0)
  1641  			opset(AMULABB, r0)
  1642  			opset(AMULA, r0)
  1643  			opset(AMULS, r0)
  1644  			opset(AMMULA, r0)
  1645  			opset(AMMULS, r0)
  1646  
  1647  		case ACLZ:
  1648  			opset(AREV, r0)
  1649  			opset(AREV16, r0)
  1650  			opset(AREVSH, r0)
  1651  			opset(ARBIT, r0)
  1652  
  1653  		case ALDREX,
  1654  			ASTREX,
  1655  			ALDREXD,
  1656  			ASTREXD,
  1657  			APLD,
  1658  			AAND,
  1659  			obj.AUNDEF,
  1660  			obj.AFUNCDATA,
  1661  			obj.APCDATA,
  1662  			obj.ANOP,
  1663  			ADATABUNDLE,
  1664  			ADATABUNDLEEND:
  1665  			break
  1666  		}
  1667  	}
  1668  }
  1669  
  1670  func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1671  	c.printp = p
  1672  	o1 := uint32(0)
  1673  	o2 := uint32(0)
  1674  	o3 := uint32(0)
  1675  	o4 := uint32(0)
  1676  	o5 := uint32(0)
  1677  	o6 := uint32(0)
  1678  	if false { /*debug['P']*/
  1679  		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  1680  	}
  1681  	switch o.type_ {
  1682  	default:
  1683  		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  1684  
  1685  	case 0: /* pseudo ops */
  1686  		if false { /*debug['G']*/
  1687  			fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
  1688  		}
  1689  
  1690  	case 1: /* op R,[R],R */
  1691  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1692  
  1693  		rf := int(p.From.Reg)
  1694  		rt := int(p.To.Reg)
  1695  		r := int(p.Reg)
  1696  		if p.To.Type == obj.TYPE_NONE {
  1697  			rt = 0
  1698  		}
  1699  		if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
  1700  			r = 0
  1701  		} else if r == 0 {
  1702  			r = rt
  1703  		}
  1704  		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1705  
  1706  	case 2: /* movbu $I,[R],R */
  1707  		c.aclass(&p.From)
  1708  
  1709  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1710  		o1 |= uint32(immrot(uint32(c.instoffset)))
  1711  		rt := int(p.To.Reg)
  1712  		r := int(p.Reg)
  1713  		if p.To.Type == obj.TYPE_NONE {
  1714  			rt = 0
  1715  		}
  1716  		if p.As == AMOVW || p.As == AMVN {
  1717  			r = 0
  1718  		} else if r == 0 {
  1719  			r = rt
  1720  		}
  1721  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1722  
  1723  	case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
  1724  		c.aclass(&p.From)
  1725  		r := int(p.Reg)
  1726  		rt := int(p.To.Reg)
  1727  		if r == 0 {
  1728  			r = rt
  1729  		}
  1730  		x, y := immrot2a(uint32(c.instoffset))
  1731  		var as2 obj.As
  1732  		switch p.As {
  1733  		case AADD, ASUB, AORR, AEOR, ABIC:
  1734  			as2 = p.As // ADD, SUB, ORR, EOR, BIC
  1735  		case ARSB:
  1736  			as2 = AADD // RSB -> RSB/ADD pair
  1737  		case AADC:
  1738  			as2 = AADD // ADC -> ADC/ADD pair
  1739  		case ASBC:
  1740  			as2 = ASUB // SBC -> SBC/SUB pair
  1741  		case ARSC:
  1742  			as2 = AADD // RSC -> RSC/ADD pair
  1743  		default:
  1744  			c.ctxt.Diag("unknown second op for %v", p)
  1745  		}
  1746  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1747  		o2 = c.oprrr(p, as2, int(p.Scond))
  1748  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1749  		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1750  		o1 |= x
  1751  		o2 |= y
  1752  
  1753  	case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
  1754  		c.aclass(&p.From)
  1755  		r := int(p.Reg)
  1756  		rt := int(p.To.Reg)
  1757  		if r == 0 {
  1758  			r = rt
  1759  		}
  1760  		y, x := immrot2s(uint32(c.instoffset))
  1761  		var as2 obj.As
  1762  		switch p.As {
  1763  		case AADD:
  1764  			as2 = ASUB // ADD -> ADD/SUB pair
  1765  		case ASUB:
  1766  			as2 = AADD // SUB -> SUB/ADD pair
  1767  		case ARSB:
  1768  			as2 = ASUB // RSB -> RSB/SUB pair
  1769  		case AADC:
  1770  			as2 = ASUB // ADC -> ADC/SUB pair
  1771  		case ASBC:
  1772  			as2 = AADD // SBC -> SBC/ADD pair
  1773  		case ARSC:
  1774  			as2 = ASUB // RSC -> RSC/SUB pair
  1775  		default:
  1776  			c.ctxt.Diag("unknown second op for %v", p)
  1777  		}
  1778  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1779  		o2 = c.oprrr(p, as2, int(p.Scond))
  1780  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1781  		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1782  		o1 |= y
  1783  		o2 |= x
  1784  
  1785  	case 3: /* add R<<[IR],[R],R */
  1786  		o1 = c.mov(p)
  1787  
  1788  	case 4: /* MOVW $off(R), R -> add $off,[R],R */
  1789  		c.aclass(&p.From)
  1790  		if c.instoffset < 0 {
  1791  			o1 = c.oprrr(p, ASUB, int(p.Scond))
  1792  			o1 |= uint32(immrot(uint32(-c.instoffset)))
  1793  		} else {
  1794  			o1 = c.oprrr(p, AADD, int(p.Scond))
  1795  			o1 |= uint32(immrot(uint32(c.instoffset)))
  1796  		}
  1797  		r := int(p.From.Reg)
  1798  		if r == 0 {
  1799  			r = int(o.param)
  1800  		}
  1801  		o1 |= (uint32(r) & 15) << 16
  1802  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1803  
  1804  	case 5: /* bra s */
  1805  		o1 = c.opbra(p, p.As, int(p.Scond))
  1806  
  1807  		v := int32(-8)
  1808  		if p.To.Sym != nil {
  1809  			rel := obj.Addrel(c.cursym)
  1810  			rel.Off = int32(c.pc)
  1811  			rel.Siz = 4
  1812  			rel.Sym = p.To.Sym
  1813  			v += int32(p.To.Offset)
  1814  			rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
  1815  			rel.Type = objabi.R_CALLARM
  1816  			break
  1817  		}
  1818  
  1819  		if p.Pcond != nil {
  1820  			v = int32((p.Pcond.Pc - c.pc) - 8)
  1821  		}
  1822  		o1 |= (uint32(v) >> 2) & 0xffffff
  1823  
  1824  	case 6: /* b ,O(R) -> add $O,R,PC */
  1825  		c.aclass(&p.To)
  1826  
  1827  		o1 = c.oprrr(p, AADD, int(p.Scond))
  1828  		o1 |= uint32(immrot(uint32(c.instoffset)))
  1829  		o1 |= (uint32(p.To.Reg) & 15) << 16
  1830  		o1 |= (REGPC & 15) << 12
  1831  
  1832  	case 7: /* bl (R) -> blx R */
  1833  		c.aclass(&p.To)
  1834  
  1835  		if c.instoffset != 0 {
  1836  			c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
  1837  		}
  1838  		o1 = c.oprrr(p, ABL, int(p.Scond))
  1839  		o1 |= (uint32(p.To.Reg) & 15) << 0
  1840  		rel := obj.Addrel(c.cursym)
  1841  		rel.Off = int32(c.pc)
  1842  		rel.Siz = 0
  1843  		rel.Type = objabi.R_CALLIND
  1844  
  1845  	case 8: /* sll $c,[R],R -> mov (R<<$c),R */
  1846  		c.aclass(&p.From)
  1847  
  1848  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1849  		r := int(p.Reg)
  1850  		if r == 0 {
  1851  			r = int(p.To.Reg)
  1852  		}
  1853  		o1 |= (uint32(r) & 15) << 0
  1854  		o1 |= uint32((c.instoffset & 31) << 7)
  1855  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1856  
  1857  	case 9: /* sll R,[R],R -> mov (R<<R),R */
  1858  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1859  
  1860  		r := int(p.Reg)
  1861  		if r == 0 {
  1862  			r = int(p.To.Reg)
  1863  		}
  1864  		o1 |= (uint32(r) & 15) << 0
  1865  		o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
  1866  		o1 |= (uint32(p.To.Reg) & 15) << 12
  1867  
  1868  	case 10: /* swi [$con] */
  1869  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1870  
  1871  		if p.To.Type != obj.TYPE_NONE {
  1872  			c.aclass(&p.To)
  1873  			o1 |= uint32(c.instoffset & 0xffffff)
  1874  		}
  1875  
  1876  	case 11: /* word */
  1877  		c.aclass(&p.To)
  1878  
  1879  		o1 = uint32(c.instoffset)
  1880  		if p.To.Sym != nil {
  1881  			// This case happens with words generated
  1882  			// in the PC stream as part of the literal pool (c.pool).
  1883  			rel := obj.Addrel(c.cursym)
  1884  
  1885  			rel.Off = int32(c.pc)
  1886  			rel.Siz = 4
  1887  			rel.Sym = p.To.Sym
  1888  			rel.Add = p.To.Offset
  1889  
  1890  			if c.ctxt.Flag_shared {
  1891  				if p.To.Name == obj.NAME_GOTREF {
  1892  					rel.Type = objabi.R_GOTPCREL
  1893  				} else {
  1894  					rel.Type = objabi.R_PCREL
  1895  				}
  1896  				rel.Add += c.pc - p.Rel.Pc - 8
  1897  			} else {
  1898  				rel.Type = objabi.R_ADDR
  1899  			}
  1900  			o1 = 0
  1901  		}
  1902  
  1903  	case 12: /* movw $lcon, reg */
  1904  		if o.a1 == C_SCON {
  1905  			o1 = c.omvs(p, &p.From, int(p.To.Reg))
  1906  		} else {
  1907  			o1 = c.omvl(p, &p.From, int(p.To.Reg))
  1908  		}
  1909  
  1910  		if o.flag&LPCREL != 0 {
  1911  			o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
  1912  		}
  1913  
  1914  	case 13: /* op $lcon, [R], R */
  1915  		if o.a1 == C_SCON {
  1916  			o1 = c.omvs(p, &p.From, REGTMP)
  1917  		} else {
  1918  			o1 = c.omvl(p, &p.From, REGTMP)
  1919  		}
  1920  
  1921  		if o1 == 0 {
  1922  			break
  1923  		}
  1924  		o2 = c.oprrr(p, p.As, int(p.Scond))
  1925  		o2 |= REGTMP & 15
  1926  		r := int(p.Reg)
  1927  		if p.As == AMOVW || p.As == AMVN {
  1928  			r = 0
  1929  		} else if r == 0 {
  1930  			r = int(p.To.Reg)
  1931  		}
  1932  		o2 |= (uint32(r) & 15) << 16
  1933  		if p.To.Type != obj.TYPE_NONE {
  1934  			o2 |= (uint32(p.To.Reg) & 15) << 12
  1935  		}
  1936  
  1937  	case 14: /* movb/movbu/movh/movhu R,R */
  1938  		o1 = c.oprrr(p, ASLL, int(p.Scond))
  1939  
  1940  		if p.As == AMOVBU || p.As == AMOVHU {
  1941  			o2 = c.oprrr(p, ASRL, int(p.Scond))
  1942  		} else {
  1943  			o2 = c.oprrr(p, ASRA, int(p.Scond))
  1944  		}
  1945  
  1946  		r := int(p.To.Reg)
  1947  		o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
  1948  		o2 |= uint32(r)&15 | (uint32(r)&15)<<12
  1949  		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  1950  			o1 |= 24 << 7
  1951  			o2 |= 24 << 7
  1952  		} else {
  1953  			o1 |= 16 << 7
  1954  			o2 |= 16 << 7
  1955  		}
  1956  
  1957  	case 15: /* mul r,[r,]r */
  1958  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1959  
  1960  		rf := int(p.From.Reg)
  1961  		rt := int(p.To.Reg)
  1962  		r := int(p.Reg)
  1963  		if r == 0 {
  1964  			r = rt
  1965  		}
  1966  		if rt == r {
  1967  			r = rf
  1968  			rf = rt
  1969  		}
  1970  
  1971  		if false {
  1972  			if rt == r || rf == REGPC&15 || r == REGPC&15 || rt == REGPC&15 {
  1973  				c.ctxt.Diag("%v: bad registers in MUL", p)
  1974  			}
  1975  		}
  1976  
  1977  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  1978  
  1979  	case 16: /* div r,[r,]r */
  1980  		o1 = 0xf << 28
  1981  
  1982  		o2 = 0
  1983  
  1984  	case 17:
  1985  		o1 = c.oprrr(p, p.As, int(p.Scond))
  1986  		rf := int(p.From.Reg)
  1987  		rt := int(p.To.Reg)
  1988  		rt2 := int(p.To.Offset)
  1989  		r := int(p.Reg)
  1990  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
  1991  
  1992  	case 20: /* mov/movb/movbu R,O(R) */
  1993  		c.aclass(&p.To)
  1994  
  1995  		r := int(p.To.Reg)
  1996  		if r == 0 {
  1997  			r = int(o.param)
  1998  		}
  1999  		o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  2000  
  2001  	case 21: /* mov/movbu O(R),R -> lr */
  2002  		c.aclass(&p.From)
  2003  
  2004  		r := int(p.From.Reg)
  2005  		if r == 0 {
  2006  			r = int(o.param)
  2007  		}
  2008  		o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  2009  		if p.As != AMOVW {
  2010  			o1 |= 1 << 22
  2011  		}
  2012  
  2013  	case 30: /* mov/movb/movbu R,L(R) */
  2014  		o1 = c.omvl(p, &p.To, REGTMP)
  2015  
  2016  		if o1 == 0 {
  2017  			break
  2018  		}
  2019  		r := int(p.To.Reg)
  2020  		if r == 0 {
  2021  			r = int(o.param)
  2022  		}
  2023  		o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  2024  		if p.As != AMOVW {
  2025  			o2 |= 1 << 22
  2026  		}
  2027  
  2028  	case 31: /* mov/movbu L(R),R -> lr[b] */
  2029  		o1 = c.omvl(p, &p.From, REGTMP)
  2030  
  2031  		if o1 == 0 {
  2032  			break
  2033  		}
  2034  		r := int(p.From.Reg)
  2035  		if r == 0 {
  2036  			r = int(o.param)
  2037  		}
  2038  		o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  2039  		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  2040  			o2 |= 1 << 22
  2041  		}
  2042  
  2043  	case 34: /* mov $lacon,R */
  2044  		o1 = c.omvl(p, &p.From, REGTMP)
  2045  
  2046  		if o1 == 0 {
  2047  			break
  2048  		}
  2049  
  2050  		o2 = c.oprrr(p, AADD, int(p.Scond))
  2051  		o2 |= REGTMP & 15
  2052  		r := int(p.From.Reg)
  2053  		if r == 0 {
  2054  			r = int(o.param)
  2055  		}
  2056  		o2 |= (uint32(r) & 15) << 16
  2057  		if p.To.Type != obj.TYPE_NONE {
  2058  			o2 |= (uint32(p.To.Reg) & 15) << 12
  2059  		}
  2060  
  2061  	case 35: /* mov PSR,R */
  2062  		o1 = 2<<23 | 0xf<<16 | 0<<0
  2063  
  2064  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2065  		o1 |= (uint32(p.From.Reg) & 1) << 22
  2066  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2067  
  2068  	case 36: /* mov R,PSR */
  2069  		o1 = 2<<23 | 0x2cf<<12 | 0<<4
  2070  
  2071  		if p.Scond&C_FBIT != 0 {
  2072  			o1 ^= 0x010 << 12
  2073  		}
  2074  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2075  		o1 |= (uint32(p.To.Reg) & 1) << 22
  2076  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2077  
  2078  	case 37: /* mov $con,PSR */
  2079  		c.aclass(&p.From)
  2080  
  2081  		o1 = 2<<23 | 0x2cf<<12 | 0<<4
  2082  		if p.Scond&C_FBIT != 0 {
  2083  			o1 ^= 0x010 << 12
  2084  		}
  2085  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2086  		o1 |= uint32(immrot(uint32(c.instoffset)))
  2087  		o1 |= (uint32(p.To.Reg) & 1) << 22
  2088  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2089  
  2090  	case 38, 39:
  2091  		switch o.type_ {
  2092  		case 38: /* movm $con,oreg -> stm */
  2093  			o1 = 0x4 << 25
  2094  
  2095  			o1 |= uint32(p.From.Offset & 0xffff)
  2096  			o1 |= (uint32(p.To.Reg) & 15) << 16
  2097  			c.aclass(&p.To)
  2098  
  2099  		case 39: /* movm oreg,$con -> ldm */
  2100  			o1 = 0x4<<25 | 1<<20
  2101  
  2102  			o1 |= uint32(p.To.Offset & 0xffff)
  2103  			o1 |= (uint32(p.From.Reg) & 15) << 16
  2104  			c.aclass(&p.From)
  2105  		}
  2106  
  2107  		if c.instoffset != 0 {
  2108  			c.ctxt.Diag("offset must be zero in MOVM; %v", p)
  2109  		}
  2110  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2111  		if p.Scond&C_PBIT != 0 {
  2112  			o1 |= 1 << 24
  2113  		}
  2114  		if p.Scond&C_UBIT != 0 {
  2115  			o1 |= 1 << 23
  2116  		}
  2117  		if p.Scond&C_WBIT != 0 {
  2118  			o1 |= 1 << 21
  2119  		}
  2120  
  2121  	case 40: /* swp oreg,reg,reg */
  2122  		c.aclass(&p.From)
  2123  
  2124  		if c.instoffset != 0 {
  2125  			c.ctxt.Diag("offset must be zero in SWP")
  2126  		}
  2127  		o1 = 0x2<<23 | 0x9<<4
  2128  		if p.As != ASWPW {
  2129  			o1 |= 1 << 22
  2130  		}
  2131  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2132  		o1 |= (uint32(p.Reg) & 15) << 0
  2133  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2134  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2135  
  2136  	case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
  2137  		o1 = 0xe8fd8000
  2138  
  2139  	case 50: /* floating point store */
  2140  		v := c.regoff(&p.To)
  2141  
  2142  		r := int(p.To.Reg)
  2143  		if r == 0 {
  2144  			r = int(o.param)
  2145  		}
  2146  		o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
  2147  
  2148  	case 51: /* floating point load */
  2149  		v := c.regoff(&p.From)
  2150  
  2151  		r := int(p.From.Reg)
  2152  		if r == 0 {
  2153  			r = int(o.param)
  2154  		}
  2155  		o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
  2156  
  2157  	case 52: /* floating point store, int32 offset UGLY */
  2158  		o1 = c.omvl(p, &p.To, REGTMP)
  2159  
  2160  		if o1 == 0 {
  2161  			break
  2162  		}
  2163  		r := int(p.To.Reg)
  2164  		if r == 0 {
  2165  			r = int(o.param)
  2166  		}
  2167  		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  2168  		o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  2169  
  2170  	case 53: /* floating point load, int32 offset UGLY */
  2171  		o1 = c.omvl(p, &p.From, REGTMP)
  2172  
  2173  		if o1 == 0 {
  2174  			break
  2175  		}
  2176  		r := int(p.From.Reg)
  2177  		if r == 0 {
  2178  			r = int(o.param)
  2179  		}
  2180  		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  2181  		o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  2182  
  2183  	case 54: /* floating point arith */
  2184  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2185  
  2186  		rf := int(p.From.Reg)
  2187  		rt := int(p.To.Reg)
  2188  		r := int(p.Reg)
  2189  		if r == 0 {
  2190  			r = rt
  2191  		}
  2192  
  2193  		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2194  
  2195  	case 55: /* negf freg, freg */
  2196  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2197  
  2198  		rf := int(p.From.Reg)
  2199  		rt := int(p.To.Reg)
  2200  
  2201  		o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
  2202  
  2203  	case 56: /* move to FP[CS]R */
  2204  		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
  2205  
  2206  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2207  
  2208  	case 57: /* move from FP[CS]R */
  2209  		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
  2210  
  2211  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2212  
  2213  	case 58: /* movbu R,R */
  2214  		o1 = c.oprrr(p, AAND, int(p.Scond))
  2215  
  2216  		o1 |= uint32(immrot(0xff))
  2217  		rt := int(p.To.Reg)
  2218  		r := int(p.From.Reg)
  2219  		if p.To.Type == obj.TYPE_NONE {
  2220  			rt = 0
  2221  		}
  2222  		if r == 0 {
  2223  			r = rt
  2224  		}
  2225  		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2226  
  2227  	case 59: /* movw/bu R<<I(R),R -> ldr indexed */
  2228  		if p.From.Reg == 0 {
  2229  			if p.As != AMOVW {
  2230  				c.ctxt.Diag("byte MOV from shifter operand")
  2231  			}
  2232  			o1 = c.mov(p)
  2233  			break
  2234  		}
  2235  
  2236  		if p.From.Offset&(1<<4) != 0 {
  2237  			c.ctxt.Diag("bad shift in LDR")
  2238  		}
  2239  		o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  2240  		if p.As == AMOVBU {
  2241  			o1 |= 1 << 22
  2242  		}
  2243  
  2244  	case 60: /* movb R(R),R -> ldrsb indexed */
  2245  		if p.From.Reg == 0 {
  2246  			c.ctxt.Diag("byte MOV from shifter operand")
  2247  			o1 = c.mov(p)
  2248  			break
  2249  		}
  2250  
  2251  		if p.From.Offset&(^0xf) != 0 {
  2252  			c.ctxt.Diag("bad shift in LDRSB")
  2253  		}
  2254  		o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  2255  		o1 ^= 1<<5 | 1<<6
  2256  
  2257  	case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
  2258  		if p.To.Reg == 0 {
  2259  			c.ctxt.Diag("MOV to shifter operand")
  2260  		}
  2261  		o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
  2262  		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  2263  			o1 |= 1 << 22
  2264  		}
  2265  
  2266  		/* reloc ops */
  2267  	case 64: /* mov/movb/movbu R,addr */
  2268  		o1 = c.omvl(p, &p.To, REGTMP)
  2269  
  2270  		if o1 == 0 {
  2271  			break
  2272  		}
  2273  		o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
  2274  		if o.flag&LPCREL != 0 {
  2275  			o3 = o2
  2276  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2277  		}
  2278  
  2279  	case 65: /* mov/movbu addr,R */
  2280  		o1 = c.omvl(p, &p.From, REGTMP)
  2281  
  2282  		if o1 == 0 {
  2283  			break
  2284  		}
  2285  		o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  2286  		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  2287  			o2 |= 1 << 22
  2288  		}
  2289  		if o.flag&LPCREL != 0 {
  2290  			o3 = o2
  2291  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2292  		}
  2293  
  2294  	case 101: /* movw tlsvar,R, local exec*/
  2295  		if p.Scond&C_SCOND != C_SCOND_NONE {
  2296  			c.ctxt.Diag("conditional tls")
  2297  		}
  2298  		o1 = c.omvl(p, &p.From, int(p.To.Reg))
  2299  
  2300  	case 102: /* movw tlsvar,R, initial exec*/
  2301  		if p.Scond&C_SCOND != C_SCOND_NONE {
  2302  			c.ctxt.Diag("conditional tls")
  2303  		}
  2304  		o1 = c.omvl(p, &p.From, int(p.To.Reg))
  2305  		o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
  2306  
  2307  	case 103: /* word tlsvar, local exec */
  2308  		if p.To.Sym == nil {
  2309  			c.ctxt.Diag("nil sym in tls %v", p)
  2310  		}
  2311  		if p.To.Offset != 0 {
  2312  			c.ctxt.Diag("offset against tls var in %v", p)
  2313  		}
  2314  		// This case happens with words generated in the PC stream as part of
  2315  		// the literal c.pool.
  2316  		rel := obj.Addrel(c.cursym)
  2317  
  2318  		rel.Off = int32(c.pc)
  2319  		rel.Siz = 4
  2320  		rel.Sym = p.To.Sym
  2321  		rel.Type = objabi.R_TLS_LE
  2322  		o1 = 0
  2323  
  2324  	case 104: /* word tlsvar, initial exec */
  2325  		if p.To.Sym == nil {
  2326  			c.ctxt.Diag("nil sym in tls %v", p)
  2327  		}
  2328  		if p.To.Offset != 0 {
  2329  			c.ctxt.Diag("offset against tls var in %v", p)
  2330  		}
  2331  		rel := obj.Addrel(c.cursym)
  2332  		rel.Off = int32(c.pc)
  2333  		rel.Siz = 4
  2334  		rel.Sym = p.To.Sym
  2335  		rel.Type = objabi.R_TLS_IE
  2336  		rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
  2337  
  2338  	case 68: /* floating point store -> ADDR */
  2339  		o1 = c.omvl(p, &p.To, REGTMP)
  2340  
  2341  		if o1 == 0 {
  2342  			break
  2343  		}
  2344  		o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  2345  		if o.flag&LPCREL != 0 {
  2346  			o3 = o2
  2347  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2348  		}
  2349  
  2350  	case 69: /* floating point load <- ADDR */
  2351  		o1 = c.omvl(p, &p.From, REGTMP)
  2352  
  2353  		if o1 == 0 {
  2354  			break
  2355  		}
  2356  		o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  2357  		if o.flag&LPCREL != 0 {
  2358  			o3 = o2
  2359  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2360  		}
  2361  
  2362  		/* ArmV4 ops: */
  2363  	case 70: /* movh/movhu R,O(R) -> strh */
  2364  		c.aclass(&p.To)
  2365  
  2366  		r := int(p.To.Reg)
  2367  		if r == 0 {
  2368  			r = int(o.param)
  2369  		}
  2370  		o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  2371  
  2372  	case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
  2373  		c.aclass(&p.From)
  2374  
  2375  		r := int(p.From.Reg)
  2376  		if r == 0 {
  2377  			r = int(o.param)
  2378  		}
  2379  		o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  2380  		if p.As == AMOVB || p.As == AMOVBS {
  2381  			o1 ^= 1<<5 | 1<<6
  2382  		} else if p.As == AMOVH || p.As == AMOVHS {
  2383  			o1 ^= (1 << 6)
  2384  		}
  2385  
  2386  	case 72: /* movh/movhu R,L(R) -> strh */
  2387  		o1 = c.omvl(p, &p.To, REGTMP)
  2388  
  2389  		if o1 == 0 {
  2390  			break
  2391  		}
  2392  		r := int(p.To.Reg)
  2393  		if r == 0 {
  2394  			r = int(o.param)
  2395  		}
  2396  		o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  2397  
  2398  	case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
  2399  		o1 = c.omvl(p, &p.From, REGTMP)
  2400  
  2401  		if o1 == 0 {
  2402  			break
  2403  		}
  2404  		r := int(p.From.Reg)
  2405  		if r == 0 {
  2406  			r = int(o.param)
  2407  		}
  2408  		o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  2409  		if p.As == AMOVB || p.As == AMOVBS {
  2410  			o2 ^= 1<<5 | 1<<6
  2411  		} else if p.As == AMOVH || p.As == AMOVHS {
  2412  			o2 ^= (1 << 6)
  2413  		}
  2414  
  2415  	case 74: /* bx $I */
  2416  		c.ctxt.Diag("ABX $I")
  2417  
  2418  	case 75: /* bx O(R) */
  2419  		c.aclass(&p.To)
  2420  
  2421  		if c.instoffset != 0 {
  2422  			c.ctxt.Diag("non-zero offset in ABX")
  2423  		}
  2424  
  2425  		/*
  2426  			o1 = 	c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12);	// mov PC, LR
  2427  			o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0);		// BX R
  2428  		*/
  2429  		// p->to.reg may be REGLINK
  2430  		o1 = c.oprrr(p, AADD, int(p.Scond))
  2431  
  2432  		o1 |= uint32(immrot(uint32(c.instoffset)))
  2433  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2434  		o1 |= (REGTMP & 15) << 12
  2435  		o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
  2436  		o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15            // BX Rtmp
  2437  
  2438  	case 76: /* bx O(R) when returning from fn*/
  2439  		c.ctxt.Diag("ABXRET")
  2440  
  2441  	case 77: /* ldrex oreg,reg */
  2442  		c.aclass(&p.From)
  2443  
  2444  		if c.instoffset != 0 {
  2445  			c.ctxt.Diag("offset must be zero in LDREX")
  2446  		}
  2447  		o1 = 0x19<<20 | 0xf9f
  2448  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2449  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2450  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2451  
  2452  	case 78: /* strex reg,oreg,reg */
  2453  		c.aclass(&p.From)
  2454  
  2455  		if c.instoffset != 0 {
  2456  			c.ctxt.Diag("offset must be zero in STREX")
  2457  		}
  2458  		o1 = 0x18<<20 | 0xf90
  2459  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2460  		o1 |= (uint32(p.Reg) & 15) << 0
  2461  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2462  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2463  
  2464  	case 80: /* fmov zfcon,freg */
  2465  		if p.As == AMOVD {
  2466  			o1 = 0xeeb00b00 // VMOV imm 64
  2467  			o2 = c.oprrr(p, ASUBD, int(p.Scond))
  2468  		} else {
  2469  			o1 = 0x0eb00a00 // VMOV imm 32
  2470  			o2 = c.oprrr(p, ASUBF, int(p.Scond))
  2471  		}
  2472  
  2473  		v := int32(0x70) // 1.0
  2474  		r := (int(p.To.Reg) & 15) << 0
  2475  
  2476  		// movf $1.0, r
  2477  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2478  
  2479  		o1 |= (uint32(r) & 15) << 12
  2480  		o1 |= (uint32(v) & 0xf) << 0
  2481  		o1 |= (uint32(v) & 0xf0) << 12
  2482  
  2483  		// subf r,r,r
  2484  		o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
  2485  
  2486  	case 81: /* fmov sfcon,freg */
  2487  		o1 = 0x0eb00a00 // VMOV imm 32
  2488  		if p.As == AMOVD {
  2489  			o1 = 0xeeb00b00 // VMOV imm 64
  2490  		}
  2491  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2492  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2493  		v := int32(c.chipfloat5(p.From.Val.(float64)))
  2494  		o1 |= (uint32(v) & 0xf) << 0
  2495  		o1 |= (uint32(v) & 0xf0) << 12
  2496  
  2497  	case 82: /* fcmp freg,freg, */
  2498  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2499  
  2500  		o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
  2501  		o2 = 0x0ef1fa10 // VMRS R15
  2502  		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2503  
  2504  	case 83: /* fcmp freg,, */
  2505  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2506  
  2507  		o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
  2508  		o2 = 0x0ef1fa10 // VMRS R15
  2509  		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2510  
  2511  	case 84: /* movfw freg,freg - truncate float-to-fix */
  2512  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2513  
  2514  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2515  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2516  
  2517  	case 85: /* movwf freg,freg - fix-to-float */
  2518  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2519  
  2520  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2521  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2522  
  2523  		// macro for movfw freg,FTMP; movw FTMP,reg
  2524  	case 86: /* movfw freg,reg - truncate float-to-fix */
  2525  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2526  
  2527  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2528  		o1 |= (FREGTMP & 15) << 12
  2529  		o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2530  		o2 |= (FREGTMP & 15) << 16
  2531  		o2 |= (uint32(p.To.Reg) & 15) << 12
  2532  
  2533  		// macro for movw reg,FTMP; movwf FTMP,freg
  2534  	case 87: /* movwf reg,freg - fix-to-float */
  2535  		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2536  
  2537  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2538  		o1 |= (FREGTMP & 15) << 16
  2539  		o2 = c.oprrr(p, p.As, int(p.Scond))
  2540  		o2 |= (FREGTMP & 15) << 0
  2541  		o2 |= (uint32(p.To.Reg) & 15) << 12
  2542  
  2543  	case 88: /* movw reg,freg  */
  2544  		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2545  
  2546  		o1 |= (uint32(p.From.Reg) & 15) << 12
  2547  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2548  
  2549  	case 89: /* movw freg,reg  */
  2550  		o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2551  
  2552  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2553  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2554  
  2555  	case 91: /* ldrexd oreg,reg */
  2556  		c.aclass(&p.From)
  2557  
  2558  		if c.instoffset != 0 {
  2559  			c.ctxt.Diag("offset must be zero in LDREX")
  2560  		}
  2561  		o1 = 0x1b<<20 | 0xf9f
  2562  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2563  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2564  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2565  
  2566  	case 92: /* strexd reg,oreg,reg */
  2567  		c.aclass(&p.From)
  2568  
  2569  		if c.instoffset != 0 {
  2570  			c.ctxt.Diag("offset must be zero in STREX")
  2571  		}
  2572  		o1 = 0x1a<<20 | 0xf90
  2573  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2574  		o1 |= (uint32(p.Reg) & 15) << 0
  2575  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2576  		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2577  
  2578  	case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
  2579  		o1 = c.omvl(p, &p.From, REGTMP)
  2580  
  2581  		if o1 == 0 {
  2582  			break
  2583  		}
  2584  		o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  2585  		if p.As == AMOVB || p.As == AMOVBS {
  2586  			o2 ^= 1<<5 | 1<<6
  2587  		} else if p.As == AMOVH || p.As == AMOVHS {
  2588  			o2 ^= (1 << 6)
  2589  		}
  2590  		if o.flag&LPCREL != 0 {
  2591  			o3 = o2
  2592  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2593  		}
  2594  
  2595  	case 94: /* movh/movhu R,addr -> strh */
  2596  		o1 = c.omvl(p, &p.To, REGTMP)
  2597  
  2598  		if o1 == 0 {
  2599  			break
  2600  		}
  2601  		o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
  2602  		if o.flag&LPCREL != 0 {
  2603  			o3 = o2
  2604  			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2605  		}
  2606  
  2607  	case 95: /* PLD off(reg) */
  2608  		o1 = 0xf5d0f000
  2609  
  2610  		o1 |= (uint32(p.From.Reg) & 15) << 16
  2611  		if p.From.Offset < 0 {
  2612  			o1 &^= (1 << 23)
  2613  			o1 |= uint32((-p.From.Offset) & 0xfff)
  2614  		} else {
  2615  			o1 |= uint32(p.From.Offset & 0xfff)
  2616  		}
  2617  
  2618  	// This is supposed to be something that stops execution.
  2619  	// It's not supposed to be reached, ever, but if it is, we'd
  2620  	// like to be able to tell how we got there. Assemble as
  2621  	// 0xf7fabcfd which is guaranteed to raise undefined instruction
  2622  	// exception.
  2623  	case 96: /* UNDEF */
  2624  		o1 = 0xf7fabcfd
  2625  
  2626  	case 97: /* CLZ Rm, Rd */
  2627  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2628  
  2629  		o1 |= (uint32(p.To.Reg) & 15) << 12
  2630  		o1 |= (uint32(p.From.Reg) & 15) << 0
  2631  
  2632  	case 98: /* MULW{T,B} Rs, Rm, Rd */
  2633  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2634  
  2635  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2636  		o1 |= (uint32(p.From.Reg) & 15) << 8
  2637  		o1 |= (uint32(p.Reg) & 15) << 0
  2638  
  2639  	case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
  2640  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2641  
  2642  		o1 |= (uint32(p.To.Reg) & 15) << 16
  2643  		o1 |= (uint32(p.From.Reg) & 15) << 8
  2644  		o1 |= (uint32(p.Reg) & 15) << 0
  2645  		o1 |= uint32((p.To.Offset & 15) << 12)
  2646  
  2647  	// DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
  2648  	// DATABUNDLEEND: zero width alignment marker
  2649  	case 100:
  2650  		if p.As == ADATABUNDLE {
  2651  			o1 = 0xe125be70
  2652  		}
  2653  
  2654  	case 105: /* divhw r,[r,]r */
  2655  		o1 = c.oprrr(p, p.As, int(p.Scond))
  2656  		rf := int(p.From.Reg)
  2657  		rt := int(p.To.Reg)
  2658  		r := int(p.Reg)
  2659  		if r == 0 {
  2660  			r = rt
  2661  		}
  2662  		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  2663  	}
  2664  
  2665  	out[0] = o1
  2666  	out[1] = o2
  2667  	out[2] = o3
  2668  	out[3] = o4
  2669  	out[4] = o5
  2670  	out[5] = o6
  2671  	return
  2672  }
  2673  
  2674  func (c *ctxt5) mov(p *obj.Prog) uint32 {
  2675  	c.aclass(&p.From)
  2676  	o1 := c.oprrr(p, p.As, int(p.Scond))
  2677  	o1 |= uint32(p.From.Offset)
  2678  	rt := int(p.To.Reg)
  2679  	if p.To.Type == obj.TYPE_NONE {
  2680  		rt = 0
  2681  	}
  2682  	r := int(p.Reg)
  2683  	if p.As == AMOVW || p.As == AMVN {
  2684  		r = 0
  2685  	} else if r == 0 {
  2686  		r = rt
  2687  	}
  2688  	o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2689  	return o1
  2690  }
  2691  
  2692  func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
  2693  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2694  	if sc&C_SBIT != 0 {
  2695  		o |= 1 << 20
  2696  	}
  2697  	switch a {
  2698  	case ADIVHW:
  2699  		return o | 0x71<<20 | 0xf<<12 | 0x1<<4
  2700  	case ADIVUHW:
  2701  		return o | 0x73<<20 | 0xf<<12 | 0x1<<4
  2702  	case AMMUL:
  2703  		return o | 0x75<<20 | 0xf<<12 | 0x1<<4
  2704  	case AMULS:
  2705  		return o | 0x6<<20 | 0x9<<4
  2706  	case AMMULA:
  2707  		return o | 0x75<<20 | 0x1<<4
  2708  	case AMMULS:
  2709  		return o | 0x75<<20 | 0xd<<4
  2710  	case AMULU, AMUL:
  2711  		return o | 0x0<<21 | 0x9<<4
  2712  	case AMULA:
  2713  		return o | 0x1<<21 | 0x9<<4
  2714  	case AMULLU:
  2715  		return o | 0x4<<21 | 0x9<<4
  2716  	case AMULL:
  2717  		return o | 0x6<<21 | 0x9<<4
  2718  	case AMULALU:
  2719  		return o | 0x5<<21 | 0x9<<4
  2720  	case AMULAL:
  2721  		return o | 0x7<<21 | 0x9<<4
  2722  	case AAND:
  2723  		return o | 0x0<<21
  2724  	case AEOR:
  2725  		return o | 0x1<<21
  2726  	case ASUB:
  2727  		return o | 0x2<<21
  2728  	case ARSB:
  2729  		return o | 0x3<<21
  2730  	case AADD:
  2731  		return o | 0x4<<21
  2732  	case AADC:
  2733  		return o | 0x5<<21
  2734  	case ASBC:
  2735  		return o | 0x6<<21
  2736  	case ARSC:
  2737  		return o | 0x7<<21
  2738  	case ATST:
  2739  		return o | 0x8<<21 | 1<<20
  2740  	case ATEQ:
  2741  		return o | 0x9<<21 | 1<<20
  2742  	case ACMP:
  2743  		return o | 0xa<<21 | 1<<20
  2744  	case ACMN:
  2745  		return o | 0xb<<21 | 1<<20
  2746  	case AORR:
  2747  		return o | 0xc<<21
  2748  
  2749  	case AMOVB, AMOVH, AMOVW:
  2750  		if sc&(C_PBIT|C_WBIT) != 0 {
  2751  			c.ctxt.Diag("invalid .P/.W suffix: %v", p)
  2752  		}
  2753  		return o | 0xd<<21
  2754  	case ABIC:
  2755  		return o | 0xe<<21
  2756  	case AMVN:
  2757  		return o | 0xf<<21
  2758  	case ASLL:
  2759  		return o | 0xd<<21 | 0<<5
  2760  	case ASRL:
  2761  		return o | 0xd<<21 | 1<<5
  2762  	case ASRA:
  2763  		return o | 0xd<<21 | 2<<5
  2764  	case ASWI:
  2765  		return o | 0xf<<24
  2766  
  2767  	case AADDD:
  2768  		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
  2769  	case AADDF:
  2770  		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
  2771  	case ASUBD:
  2772  		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
  2773  	case ASUBF:
  2774  		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
  2775  	case AMULD:
  2776  		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
  2777  	case AMULF:
  2778  		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
  2779  	case ADIVD:
  2780  		return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
  2781  	case ADIVF:
  2782  		return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
  2783  	case ASQRTD:
  2784  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
  2785  	case ASQRTF:
  2786  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
  2787  	case AABSD:
  2788  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
  2789  	case AABSF:
  2790  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
  2791  	case ANEGD:
  2792  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
  2793  	case ANEGF:
  2794  		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
  2795  	case ACMPD:
  2796  		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
  2797  	case ACMPF:
  2798  		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
  2799  
  2800  	case AMOVF:
  2801  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
  2802  	case AMOVD:
  2803  		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
  2804  
  2805  	case AMOVDF:
  2806  		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
  2807  	case AMOVFD:
  2808  		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
  2809  
  2810  	case AMOVWF:
  2811  		if sc&C_UBIT == 0 {
  2812  			o |= 1 << 7 /* signed */
  2813  		}
  2814  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
  2815  
  2816  	case AMOVWD:
  2817  		if sc&C_UBIT == 0 {
  2818  			o |= 1 << 7 /* signed */
  2819  		}
  2820  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
  2821  
  2822  	case AMOVFW:
  2823  		if sc&C_UBIT == 0 {
  2824  			o |= 1 << 16 /* signed */
  2825  		}
  2826  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
  2827  
  2828  	case AMOVDW:
  2829  		if sc&C_UBIT == 0 {
  2830  			o |= 1 << 16 /* signed */
  2831  		}
  2832  		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
  2833  
  2834  	case -AMOVWF: // copy WtoF
  2835  		return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
  2836  
  2837  	case -AMOVFW: // copy FtoW
  2838  		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
  2839  
  2840  	case -ACMP: // cmp imm
  2841  		return o | 0x3<<24 | 0x5<<20
  2842  
  2843  		// CLZ doesn't support .nil
  2844  	case ACLZ:
  2845  		return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
  2846  
  2847  	case AREV:
  2848  		return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
  2849  
  2850  	case AREV16:
  2851  		return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
  2852  
  2853  	case AREVSH:
  2854  		return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
  2855  
  2856  	case ARBIT:
  2857  		return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
  2858  
  2859  	case AMULWT:
  2860  		return o&(0xf<<28) | 0x12<<20 | 0xe<<4
  2861  
  2862  	case AMULWB:
  2863  		return o&(0xf<<28) | 0x12<<20 | 0xa<<4
  2864  
  2865  	case AMULBB:
  2866  		return o&(0xf<<28) | 0x16<<20 | 0xf<<12 | 0x8<<4
  2867  
  2868  	case AMULAWT:
  2869  		return o&(0xf<<28) | 0x12<<20 | 0xc<<4
  2870  
  2871  	case AMULAWB:
  2872  		return o&(0xf<<28) | 0x12<<20 | 0x8<<4
  2873  
  2874  	case AMULABB:
  2875  		return o&(0xf<<28) | 0x10<<20 | 0x8<<4
  2876  
  2877  	case ABL: // BLX REG
  2878  		return o&(0xf<<28) | 0x12fff3<<4
  2879  	}
  2880  
  2881  	c.ctxt.Diag("%v: bad rrr %d", p, a)
  2882  	return 0
  2883  }
  2884  
  2885  func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
  2886  	sc &= C_SCOND
  2887  	sc ^= C_SCOND_XOR
  2888  	if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
  2889  		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
  2890  	}
  2891  	if sc != 0xe {
  2892  		c.ctxt.Diag("%v: .COND on bcond instruction", p)
  2893  	}
  2894  	switch a {
  2895  	case ABEQ:
  2896  		return 0x0<<28 | 0x5<<25
  2897  	case ABNE:
  2898  		return 0x1<<28 | 0x5<<25
  2899  	case ABCS:
  2900  		return 0x2<<28 | 0x5<<25
  2901  	case ABHS:
  2902  		return 0x2<<28 | 0x5<<25
  2903  	case ABCC:
  2904  		return 0x3<<28 | 0x5<<25
  2905  	case ABLO:
  2906  		return 0x3<<28 | 0x5<<25
  2907  	case ABMI:
  2908  		return 0x4<<28 | 0x5<<25
  2909  	case ABPL:
  2910  		return 0x5<<28 | 0x5<<25
  2911  	case ABVS:
  2912  		return 0x6<<28 | 0x5<<25
  2913  	case ABVC:
  2914  		return 0x7<<28 | 0x5<<25
  2915  	case ABHI:
  2916  		return 0x8<<28 | 0x5<<25
  2917  	case ABLS:
  2918  		return 0x9<<28 | 0x5<<25
  2919  	case ABGE:
  2920  		return 0xa<<28 | 0x5<<25
  2921  	case ABLT:
  2922  		return 0xb<<28 | 0x5<<25
  2923  	case ABGT:
  2924  		return 0xc<<28 | 0x5<<25
  2925  	case ABLE:
  2926  		return 0xd<<28 | 0x5<<25
  2927  	case AB:
  2928  		return 0xe<<28 | 0x5<<25
  2929  	}
  2930  
  2931  	c.ctxt.Diag("%v: bad bra %v", p, a)
  2932  	return 0
  2933  }
  2934  
  2935  func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
  2936  	if sc&C_SBIT != 0 {
  2937  		c.ctxt.Diag(".nil on LDR/STR instruction")
  2938  	}
  2939  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2940  	if sc&C_PBIT == 0 {
  2941  		o |= 1 << 24
  2942  	}
  2943  	if sc&C_UBIT == 0 {
  2944  		o |= 1 << 23
  2945  	}
  2946  	if sc&C_WBIT != 0 {
  2947  		o |= 1 << 21
  2948  	}
  2949  	o |= 1<<26 | 1<<20
  2950  	if v < 0 {
  2951  		if sc&C_UBIT != 0 {
  2952  			c.ctxt.Diag(".U on neg offset")
  2953  		}
  2954  		v = -v
  2955  		o ^= 1 << 23
  2956  	}
  2957  
  2958  	if v >= 1<<12 || v < 0 {
  2959  		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  2960  	}
  2961  	o |= uint32(v)
  2962  	o |= (uint32(b) & 15) << 16
  2963  	o |= (uint32(r) & 15) << 12
  2964  	return o
  2965  }
  2966  
  2967  func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
  2968  	if sc&C_SBIT != 0 {
  2969  		c.ctxt.Diag(".nil on LDRH/STRH instruction")
  2970  	}
  2971  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2972  	if sc&C_PBIT == 0 {
  2973  		o |= 1 << 24
  2974  	}
  2975  	if sc&C_WBIT != 0 {
  2976  		o |= 1 << 21
  2977  	}
  2978  	o |= 1<<23 | 1<<20 | 0xb<<4
  2979  	if v < 0 {
  2980  		v = -v
  2981  		o ^= 1 << 23
  2982  	}
  2983  
  2984  	if v >= 1<<8 || v < 0 {
  2985  		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  2986  	}
  2987  	o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
  2988  	o |= (uint32(b) & 15) << 16
  2989  	o |= (uint32(r) & 15) << 12
  2990  	return o
  2991  }
  2992  
  2993  func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
  2994  	o := c.olr(v, b, r, sc) ^ (1 << 20)
  2995  	if a != AMOVW {
  2996  		o |= 1 << 22
  2997  	}
  2998  	return o
  2999  }
  3000  
  3001  func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
  3002  	o := c.olhr(v, b, r, sc) ^ (1 << 20)
  3003  	return o
  3004  }
  3005  
  3006  func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
  3007  	return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
  3008  }
  3009  
  3010  func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
  3011  	return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
  3012  }
  3013  
  3014  func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
  3015  	return c.olr(int32(i), b, r, sc) ^ (1 << 25)
  3016  }
  3017  
  3018  func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
  3019  	return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
  3020  }
  3021  
  3022  func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
  3023  	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  3024  	if sc&C_PBIT == 0 {
  3025  		o |= 1 << 24
  3026  	}
  3027  	if sc&C_WBIT != 0 {
  3028  		o |= 1 << 21
  3029  	}
  3030  	o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
  3031  	if v < 0 {
  3032  		v = -v
  3033  		o ^= 1 << 23
  3034  	}
  3035  
  3036  	if v&3 != 0 {
  3037  		c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
  3038  	} else if v >= 1<<10 || v < 0 {
  3039  		c.ctxt.Diag("literal span too large: %d\n%v", v, p)
  3040  	}
  3041  	o |= (uint32(v) >> 2) & 0xFF
  3042  	o |= (uint32(b) & 15) << 16
  3043  	o |= (uint32(r) & 15) << 12
  3044  
  3045  	switch a {
  3046  	default:
  3047  		c.ctxt.Diag("bad fst %v", a)
  3048  		fallthrough
  3049  
  3050  	case AMOVD:
  3051  		o |= 1 << 8
  3052  		fallthrough
  3053  
  3054  	case AMOVF:
  3055  		break
  3056  	}
  3057  
  3058  	return o
  3059  }
  3060  
  3061  // MOVW $"lower 16-bit", Reg
  3062  func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  3063  	var o1 uint32
  3064  	o1 = ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  3065  	o1 |= 0x30 << 20
  3066  	o1 |= (uint32(dr) & 15) << 12
  3067  	o1 |= uint32(a.Offset) & 0x0fff
  3068  	o1 |= (uint32(a.Offset) & 0xf000) << 4
  3069  	return o1
  3070  }
  3071  
  3072  func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  3073  	var o1 uint32
  3074  	if p.Pcond == nil {
  3075  		c.aclass(a)
  3076  		v := immrot(^uint32(c.instoffset))
  3077  		if v == 0 {
  3078  			c.ctxt.Diag("%v: missing literal", p)
  3079  			return 0
  3080  		}
  3081  
  3082  		o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
  3083  		o1 |= uint32(v)
  3084  		o1 |= (uint32(dr) & 15) << 12
  3085  	} else {
  3086  		v := int32(p.Pcond.Pc - p.Pc - 8)
  3087  		o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
  3088  	}
  3089  
  3090  	return o1
  3091  }
  3092  
  3093  func (c *ctxt5) chipzero5(e float64) int {
  3094  	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  3095  	if objabi.GOARM < 7 || e != 0 {
  3096  		return -1
  3097  	}
  3098  	return 0
  3099  }
  3100  
  3101  func (c *ctxt5) chipfloat5(e float64) int {
  3102  	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  3103  	if objabi.GOARM < 7 {
  3104  		return -1
  3105  	}
  3106  
  3107  	ei := math.Float64bits(e)
  3108  	l := uint32(ei)
  3109  	h := uint32(ei >> 32)
  3110  
  3111  	if l != 0 || h&0xffff != 0 {
  3112  		return -1
  3113  	}
  3114  	h1 := h & 0x7fc00000
  3115  	if h1 != 0x40000000 && h1 != 0x3fc00000 {
  3116  		return -1
  3117  	}
  3118  	n := 0
  3119  
  3120  	// sign bit (a)
  3121  	if h&0x80000000 != 0 {
  3122  		n |= 1 << 7
  3123  	}
  3124  
  3125  	// exp sign bit (b)
  3126  	if h1 == 0x3fc00000 {
  3127  		n |= 1 << 6
  3128  	}
  3129  
  3130  	// rest of exp and mantissa (cd-efgh)
  3131  	n |= int((h >> 16) & 0x3f)
  3132  
  3133  	//print("match %.8lux %.8lux %d\n", l, h, n);
  3134  	return n
  3135  }
  3136  
  3137  func nocache(p *obj.Prog) {
  3138  	p.Optab = 0
  3139  	p.From.Class = 0
  3140  	if p.From3 != nil {
  3141  		p.From3.Class = 0
  3142  	}
  3143  	p.To.Class = 0
  3144  }