...

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

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

View as plain text