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