...

Source file src/pkg/cmd/internal/obj/arm64/asm7.go

     1	// cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
     2	// https://code.google.com/p/ken-cc/source/browse/
     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 arm64
    32	
    33	import (
    34		"cmd/internal/obj"
    35		"cmd/internal/objabi"
    36		"fmt"
    37		"log"
    38		"math"
    39		"sort"
    40	)
    41	
    42	// ctxt7 holds state while assembling a single function.
    43	// Each function gets a fresh ctxt7.
    44	// This allows for multiple functions to be safely concurrently assembled.
    45	type ctxt7 struct {
    46		ctxt       *obj.Link
    47		newprog    obj.ProgAlloc
    48		cursym     *obj.LSym
    49		blitrl     *obj.Prog
    50		elitrl     *obj.Prog
    51		autosize   int32
    52		extrasize  int32
    53		instoffset int64
    54		pc         int64
    55		pool       struct {
    56			start uint32
    57			size  uint32
    58		}
    59	}
    60	
    61	const (
    62		funcAlign = 16
    63	)
    64	
    65	const (
    66		REGFROM = 1
    67	)
    68	
    69	type Optab struct {
    70		as    obj.As
    71		a1    uint8
    72		a2    uint8
    73		a3    uint8
    74		a4    uint8
    75		type_ int8
    76		size  int8
    77		param int16
    78		flag  int8
    79		scond uint16
    80	}
    81	
    82	func IsAtomicInstruction(as obj.As) bool {
    83		_, ok := atomicInstructions[as]
    84		return ok
    85	}
    86	
    87	// known field values of an instruction.
    88	var atomicInstructions = map[obj.As]uint32{
    89		ALDADDAD:  3<<30 | 0x1c5<<21 | 0x00<<10,
    90		ALDADDAW:  2<<30 | 0x1c5<<21 | 0x00<<10,
    91		ALDADDAH:  1<<30 | 0x1c5<<21 | 0x00<<10,
    92		ALDADDAB:  0<<30 | 0x1c5<<21 | 0x00<<10,
    93		ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
    94		ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
    95		ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
    96		ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
    97		ALDADDD:   3<<30 | 0x1c1<<21 | 0x00<<10,
    98		ALDADDW:   2<<30 | 0x1c1<<21 | 0x00<<10,
    99		ALDADDH:   1<<30 | 0x1c1<<21 | 0x00<<10,
   100		ALDADDB:   0<<30 | 0x1c1<<21 | 0x00<<10,
   101		ALDADDLD:  3<<30 | 0x1c3<<21 | 0x00<<10,
   102		ALDADDLW:  2<<30 | 0x1c3<<21 | 0x00<<10,
   103		ALDADDLH:  1<<30 | 0x1c3<<21 | 0x00<<10,
   104		ALDADDLB:  0<<30 | 0x1c3<<21 | 0x00<<10,
   105		ALDANDAD:  3<<30 | 0x1c5<<21 | 0x04<<10,
   106		ALDANDAW:  2<<30 | 0x1c5<<21 | 0x04<<10,
   107		ALDANDAH:  1<<30 | 0x1c5<<21 | 0x04<<10,
   108		ALDANDAB:  0<<30 | 0x1c5<<21 | 0x04<<10,
   109		ALDANDALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
   110		ALDANDALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
   111		ALDANDALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
   112		ALDANDALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
   113		ALDANDD:   3<<30 | 0x1c1<<21 | 0x04<<10,
   114		ALDANDW:   2<<30 | 0x1c1<<21 | 0x04<<10,
   115		ALDANDH:   1<<30 | 0x1c1<<21 | 0x04<<10,
   116		ALDANDB:   0<<30 | 0x1c1<<21 | 0x04<<10,
   117		ALDANDLD:  3<<30 | 0x1c3<<21 | 0x04<<10,
   118		ALDANDLW:  2<<30 | 0x1c3<<21 | 0x04<<10,
   119		ALDANDLH:  1<<30 | 0x1c3<<21 | 0x04<<10,
   120		ALDANDLB:  0<<30 | 0x1c3<<21 | 0x04<<10,
   121		ALDEORAD:  3<<30 | 0x1c5<<21 | 0x08<<10,
   122		ALDEORAW:  2<<30 | 0x1c5<<21 | 0x08<<10,
   123		ALDEORAH:  1<<30 | 0x1c5<<21 | 0x08<<10,
   124		ALDEORAB:  0<<30 | 0x1c5<<21 | 0x08<<10,
   125		ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
   126		ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
   127		ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
   128		ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
   129		ALDEORD:   3<<30 | 0x1c1<<21 | 0x08<<10,
   130		ALDEORW:   2<<30 | 0x1c1<<21 | 0x08<<10,
   131		ALDEORH:   1<<30 | 0x1c1<<21 | 0x08<<10,
   132		ALDEORB:   0<<30 | 0x1c1<<21 | 0x08<<10,
   133		ALDEORLD:  3<<30 | 0x1c3<<21 | 0x08<<10,
   134		ALDEORLW:  2<<30 | 0x1c3<<21 | 0x08<<10,
   135		ALDEORLH:  1<<30 | 0x1c3<<21 | 0x08<<10,
   136		ALDEORLB:  0<<30 | 0x1c3<<21 | 0x08<<10,
   137		ALDORAD:   3<<30 | 0x1c5<<21 | 0x0c<<10,
   138		ALDORAW:   2<<30 | 0x1c5<<21 | 0x0c<<10,
   139		ALDORAH:   1<<30 | 0x1c5<<21 | 0x0c<<10,
   140		ALDORAB:   0<<30 | 0x1c5<<21 | 0x0c<<10,
   141		ALDORALD:  3<<30 | 0x1c7<<21 | 0x0c<<10,
   142		ALDORALW:  2<<30 | 0x1c7<<21 | 0x0c<<10,
   143		ALDORALH:  1<<30 | 0x1c7<<21 | 0x0c<<10,
   144		ALDORALB:  0<<30 | 0x1c7<<21 | 0x0c<<10,
   145		ALDORD:    3<<30 | 0x1c1<<21 | 0x0c<<10,
   146		ALDORW:    2<<30 | 0x1c1<<21 | 0x0c<<10,
   147		ALDORH:    1<<30 | 0x1c1<<21 | 0x0c<<10,
   148		ALDORB:    0<<30 | 0x1c1<<21 | 0x0c<<10,
   149		ALDORLD:   3<<30 | 0x1c3<<21 | 0x0c<<10,
   150		ALDORLW:   2<<30 | 0x1c3<<21 | 0x0c<<10,
   151		ALDORLH:   1<<30 | 0x1c3<<21 | 0x0c<<10,
   152		ALDORLB:   0<<30 | 0x1c3<<21 | 0x0c<<10,
   153		ASWPAD:    3<<30 | 0x1c5<<21 | 0x20<<10,
   154		ASWPAW:    2<<30 | 0x1c5<<21 | 0x20<<10,
   155		ASWPAH:    1<<30 | 0x1c5<<21 | 0x20<<10,
   156		ASWPAB:    0<<30 | 0x1c5<<21 | 0x20<<10,
   157		ASWPALD:   3<<30 | 0x1c7<<21 | 0x20<<10,
   158		ASWPALW:   2<<30 | 0x1c7<<21 | 0x20<<10,
   159		ASWPALH:   1<<30 | 0x1c7<<21 | 0x20<<10,
   160		ASWPALB:   0<<30 | 0x1c7<<21 | 0x20<<10,
   161		ASWPD:     3<<30 | 0x1c1<<21 | 0x20<<10,
   162		ASWPW:     2<<30 | 0x1c1<<21 | 0x20<<10,
   163		ASWPH:     1<<30 | 0x1c1<<21 | 0x20<<10,
   164		ASWPB:     0<<30 | 0x1c1<<21 | 0x20<<10,
   165		ASWPLD:    3<<30 | 0x1c3<<21 | 0x20<<10,
   166		ASWPLW:    2<<30 | 0x1c3<<21 | 0x20<<10,
   167		ASWPLH:    1<<30 | 0x1c3<<21 | 0x20<<10,
   168		ASWPLB:    0<<30 | 0x1c3<<21 | 0x20<<10,
   169	}
   170	
   171	var oprange [ALAST & obj.AMask][]Optab
   172	
   173	var xcmp [C_NCLASS][C_NCLASS]bool
   174	
   175	const (
   176		S32     = 0 << 31
   177		S64     = 1 << 31
   178		Sbit    = 1 << 29
   179		LSL0_32 = 2 << 13
   180		LSL0_64 = 3 << 13
   181	)
   182	
   183	func OPDP2(x uint32) uint32 {
   184		return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
   185	}
   186	
   187	func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
   188		return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
   189	}
   190	
   191	func OPBcc(x uint32) uint32 {
   192		return 0x2A<<25 | 0<<24 | 0<<4 | x&15
   193	}
   194	
   195	func OPBLR(x uint32) uint32 {
   196		/* x=0, JMP; 1, CALL; 2, RET */
   197		return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
   198	}
   199	
   200	func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
   201		return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
   202	}
   203	
   204	func SYSHINT(x uint32) uint32 {
   205		return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
   206	}
   207	
   208	func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 {
   209		return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22
   210	}
   211	
   212	func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
   213		return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
   214	}
   215	
   216	func LD2STR(o uint32) uint32 {
   217		return o &^ (3 << 22)
   218	}
   219	
   220	func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
   221		return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
   222	}
   223	
   224	func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
   225		return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
   226	}
   227	
   228	func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   229		return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
   230	}
   231	
   232	func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   233		return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
   234	}
   235	
   236	func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   237		return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
   238	}
   239	
   240	func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
   241		return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
   242	}
   243	
   244	func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
   245		return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
   246	}
   247	
   248	func ADR(p uint32, o uint32, rt uint32) uint32 {
   249		return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
   250	}
   251	
   252	func OPBIT(x uint32) uint32 {
   253		return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
   254	}
   255	
   256	func MOVCONST(d int64, s int, rt int) uint32 {
   257		return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
   258	}
   259	
   260	const (
   261		LFROM = 1 << 0
   262		LTO   = 1 << 1
   263	)
   264	
   265	var optab = []Optab{
   266		/* struct Optab:
   267		OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */
   268		{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
   269	
   270		/* arithmetic operations */
   271		{AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   272		{AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   273		{AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   274		{AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   275		{ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
   276		{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
   277		{ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0},
   278		{ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
   279		{AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0},
   280		{AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0},
   281		{ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0},
   282		{AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   283		{AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   284		{ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   285		{AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   286		{AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   287		{ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   288		{AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, 0, 0},
   289		{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, 0, 0},
   290		{AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
   291		{AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
   292		{AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
   293		{AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
   294		{AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
   295		{AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
   296		{ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
   297		{ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
   298		{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
   299		{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   300		{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   301		{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   302		{ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
   303		{ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0},
   304		{AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   305		{AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   306		{ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
   307		{AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   308		{AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   309		{AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   310		{ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
   311		{AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   312		{AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   313		{AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
   314		{AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0},
   315		{AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
   316		{AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0},
   317		{AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0},
   318		{ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   319		{ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   320	
   321		{AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   322		{AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   323		{AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0},
   324		{AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
   325		{AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
   326		{AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   327		{AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   328		{AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
   329		{AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0},
   330		{AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0},
   331	
   332		/* logical operations */
   333		{AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   334		{AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   335		{AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   336		{AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   337		{ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
   338		{AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
   339		{AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   340		{AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
   341		{AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   342		{ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
   343		{AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
   344		{AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   345		{AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
   346		{AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   347		{ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
   348		{AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
   349		{AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
   350		{AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
   351		{AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
   352		{ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   353		{AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
   354		{AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
   355		{AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
   356		{AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
   357		{AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
   358		{AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
   359		{AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
   360		{AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
   361		{AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
   362		{AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
   363		{AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
   364		{AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
   365		{ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
   366		{ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
   367		{ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
   368		{AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   369		{AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   370		{AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   371		{AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   372		{ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
   373		{AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0},
   374		{AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0},
   375		{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   376		{AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   377		{AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */
   378		{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */
   379		/* TODO: MVN C_SHIFT */
   380	
   381		/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
   382		{AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   383		{AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   384		{AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   385		{AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   386		{AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0},
   387		{AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0},
   388		{AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, 0, 0},
   389		{AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, 0, 0},
   390	
   391		{AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
   392		{AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0},
   393	
   394		/* jump operations */
   395		{AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   396		{ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   397		{AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   398		{ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   399		{ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   400		{ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   401		{obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   402		{obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   403		{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
   404		{AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0},
   405		{AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0},
   406		{ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
   407		{ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0},
   408		{AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
   409	
   410		{ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
   411		{ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
   412		{ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0},
   413		{ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0},
   414		{AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0},
   415		{ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   416		{ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0},
   417		{ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0},
   418		{ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0},
   419		{ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0},
   420		{ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
   421		{ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   422		{ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   423		{ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0},
   424		{ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0},
   425		{ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0},
   426		{ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0},
   427		{AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
   428		{AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
   429		{AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
   430		{AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0},
   431		{AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0},
   432		{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   433		{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   434		{AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   435		{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   436		{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   437		{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   438		{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   439		{AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   440		{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   441		{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   442		{AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0},
   443		{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0},
   444		{AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0},
   445	
   446		{AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   447		{AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   448		{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   449		{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   450		{AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   451		{AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   452		{AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   453		{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   454		{AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   455		{AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   456		{AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   457		{AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   458		{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   459		{ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   460		{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   461		{AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0},
   462		{AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
   463		{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
   464		{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
   465		{AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
   466		{AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
   467		{AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   468		{AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
   469		{AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
   470		{AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   471		{AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
   472		{AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
   473		{AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
   474		{AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   475	
   476		/* conditional operations */
   477		{ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0},
   478		{ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0},
   479		{ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0},
   480		{AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
   481		{ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0},
   482		{ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
   483		{AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
   484	
   485		/* scaled 12-bit unsigned displacement store */
   486		{AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   487		{AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   488		{AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   489		{AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   490		{AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
   491		{AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
   492		{AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   493		{AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   494		{AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   495		{AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   496	
   497		{AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   498		{AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   499		{AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   500		{AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   501	
   502		/* unscaled 9-bit signed displacement store */
   503		{AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   504		{AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   505		{AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   506		{AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   507		{AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   508		{AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   509		{AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   510		{AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   511		{AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   512		{AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   513	
   514		{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   515		{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   516		{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   517		{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   518	
   519		/* scaled 12-bit unsigned displacement load */
   520		{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   521		{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   522		{AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   523		{AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   524		{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   525		{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   526		{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   527		{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   528		{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   529		{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   530	
   531		{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   532		{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   533		{AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   534		{AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   535	
   536		/* unscaled 9-bit signed displacement load */
   537		{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   538		{AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   539		{AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   540		{AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   541		{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   542		{AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   543		{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   544		{AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   545		{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   546		{AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   547	
   548		{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   549		{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   550		{AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   551		{AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   552	
   553		/* long displacement store */
   554		{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   555		{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   556		{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   557		{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   558		{AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   559		{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   560		{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   561		{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   562		{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   563		{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   564	
   565		{AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   566		{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   567		{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   568		{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   569	
   570		/* long displacement load */
   571		{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   572		{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   573		{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   574		{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   575		{AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   576		{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   577		{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   578		{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   579		{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   580		{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   581	
   582		{AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   583		{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   584		{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   585		{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   586	
   587		/* load long effective stack address (load int32 offset and add) */
   588		{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
   589	
   590		/* pre/post-indexed load (unscaled, signed 9-bit offset) */
   591		{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   592		{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   593		{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   594		{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   595		{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   596		{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   597		{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   598	
   599		{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   600		{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   601		{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   602		{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   603		{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   604		{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   605		{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   606	
   607		/* pre/post-indexed store (unscaled, signed 9-bit offset) */
   608		{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   609		{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   610		{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   611		{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   612		{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   613		{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   614		{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   615	
   616		{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   617		{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   618		{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   619		{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   620		{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   621		{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   622		{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   623	
   624		/* load with shifted or extended register offset */
   625		{AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   626		{AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   627		{AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   628		{AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   629		{AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   630		{AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
   631		{AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
   632	
   633		/* store with extended register offset */
   634		{AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   635		{AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   636		{AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   637		{AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   638		{AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   639		{AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   640	
   641		/* pre/post-indexed/signed-offset load/store register pair
   642		   (unscaled, signed 10-bit quad-aligned and long offset) */
   643		{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   644		{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   645		{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   646		{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   647		{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   648		{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   649		{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   650		{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
   651		{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
   652		{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   653		{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
   654		{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
   655		{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   656		{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
   657		{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
   658		{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   659		{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   660		{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   661		{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   662		{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   663		{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   664		{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   665		{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
   666		{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
   667		{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   668		{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
   669		{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
   670		{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   671		{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
   672		{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
   673		{ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   674	
   675		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
   676		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
   677		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
   678		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
   679		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
   680		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
   681		{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   682		{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
   683		{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
   684		{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
   685		{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
   686		{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
   687		{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   688		{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
   689		{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
   690		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
   691		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
   692		{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
   693		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
   694		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
   695		{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
   696		{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   697		{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
   698		{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
   699		{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
   700		{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
   701		{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
   702		{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   703		{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
   704		{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
   705		{ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   706	
   707		// differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
   708		{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   709		{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   710		{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   711		{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   712		{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   713		{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   714		{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   715		{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
   716		{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
   717		{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   718		{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
   719		{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
   720		{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   721		{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
   722		{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
   723		{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   724		{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   725		{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   726		{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   727		{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   728		{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   729		{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   730		{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
   731		{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
   732		{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   733		{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
   734		{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
   735		{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   736		{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
   737		{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
   738		{ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   739	
   740		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
   741		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
   742		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
   743		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
   744		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
   745		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
   746		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   747		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
   748		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
   749		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
   750		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
   751		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
   752		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   753		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
   754		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
   755		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
   756		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
   757		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
   758		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
   759		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
   760		{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
   761		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   762		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
   763		{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
   764		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
   765		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
   766		{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
   767		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   768		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
   769		{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
   770		{ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   771	
   772		{ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0},     // RegTo2=C_REG
   773		{ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG
   774		{ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   775		{ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   776		{ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   777		{ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
   778		{ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_NONE
   779		{ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_REG
   780		{ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
   781		{ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
   782	
   783		/* VLD1/VST1 */
   784		{AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
   785		{AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   786		{AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   787		{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
   788		{AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
   789		{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
   790		{AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   791		{AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   792		{AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   793		{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
   794		{AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
   795		{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
   796	
   797		/* special */
   798		{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
   799		{AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
   800		{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   801		{AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   802		{AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   803		{AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   804		{APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0},
   805		{APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
   806		{ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
   807		{AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
   808		{ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
   809		{ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0},
   810		{ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0},
   811	
   812		/* encryption instructions */
   813		{AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
   814		{AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
   815		{ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   816		{ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   817		{ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0},
   818		{ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0},
   819		{ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   820		{AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   821		{AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0},
   822	
   823		{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
   824		{obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
   825		{obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
   826		{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   827		{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   828		{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   829	
   830		{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
   831	}
   832	
   833	/*
   834	 * valid pstate field values, and value to use in instruction
   835	 */
   836	var pstatefield = []struct {
   837		reg int16
   838		enc uint32
   839	}{
   840		{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
   841		{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
   842		{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
   843	}
   844	
   845	// the System register values, and value to use in instruction
   846	var systemreg = []struct {
   847		reg int16
   848		enc uint32
   849	}{
   850		{REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5},
   851		{REG_DCZID_EL0, 3<<19 | 3<<16 | 7<<5},
   852	}
   853	
   854	var prfopfield = []struct {
   855		reg int16
   856		enc uint32
   857	}{
   858		{REG_PLDL1KEEP, 0},
   859		{REG_PLDL1STRM, 1},
   860		{REG_PLDL2KEEP, 2},
   861		{REG_PLDL2STRM, 3},
   862		{REG_PLDL3KEEP, 4},
   863		{REG_PLDL3STRM, 5},
   864		{REG_PLIL1KEEP, 8},
   865		{REG_PLIL1STRM, 9},
   866		{REG_PLIL2KEEP, 10},
   867		{REG_PLIL2STRM, 11},
   868		{REG_PLIL3KEEP, 12},
   869		{REG_PLIL3STRM, 13},
   870		{REG_PSTL1KEEP, 16},
   871		{REG_PSTL1STRM, 17},
   872		{REG_PSTL2KEEP, 18},
   873		{REG_PSTL2STRM, 19},
   874		{REG_PSTL3KEEP, 20},
   875		{REG_PSTL3STRM, 21},
   876	}
   877	
   878	func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   879		p := cursym.Func.Text
   880		if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   881			return
   882		}
   883	
   884		if oprange[AAND&obj.AMask] == nil {
   885			ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
   886		}
   887	
   888		c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
   889		p.To.Offset &= 0xffffffff // extrasize is no longer needed
   890	
   891		bflag := 1
   892		pc := int64(0)
   893		p.Pc = pc
   894		var m int
   895		var o *Optab
   896		for p = p.Link; p != nil; p = p.Link {
   897			if p.As == ADWORD && (pc&7) != 0 {
   898				pc += 4
   899			}
   900			p.Pc = pc
   901			o = c.oplook(p)
   902			m = int(o.size)
   903			if m == 0 {
   904				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
   905					c.ctxt.Diag("zero-width instruction\n%v", p)
   906				}
   907				continue
   908			}
   909	
   910			switch o.flag & (LFROM | LTO) {
   911			case LFROM:
   912				c.addpool(p, &p.From)
   913	
   914			case LTO:
   915				c.addpool(p, &p.To)
   916				break
   917			}
   918	
   919			if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
   920				c.checkpool(p, 0)
   921			}
   922			pc += int64(m)
   923			if c.blitrl != nil {
   924				c.checkpool(p, 1)
   925			}
   926		}
   927	
   928		c.cursym.Size = pc
   929	
   930		/*
   931		 * if any procedure is large enough to
   932		 * generate a large SBRA branch, then
   933		 * generate extra passes putting branches
   934		 * around jmps to fix. this is rare.
   935		 */
   936		for bflag != 0 {
   937			bflag = 0
   938			pc = 0
   939			for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
   940				if p.As == ADWORD && (pc&7) != 0 {
   941					pc += 4
   942				}
   943				p.Pc = pc
   944				o = c.oplook(p)
   945	
   946				/* very large branches */
   947				if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
   948					otxt := p.Pcond.Pc - pc
   949					var toofar bool
   950					switch o.type_ {
   951					case 7, 39: // branch instruction encodes 19 bits
   952						toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
   953					case 40: // branch instruction encodes 14 bits
   954						toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
   955					}
   956					if toofar {
   957						q := c.newprog()
   958						q.Link = p.Link
   959						p.Link = q
   960						q.As = AB
   961						q.To.Type = obj.TYPE_BRANCH
   962						q.Pcond = p.Pcond
   963						p.Pcond = q
   964						q = c.newprog()
   965						q.Link = p.Link
   966						p.Link = q
   967						q.As = AB
   968						q.To.Type = obj.TYPE_BRANCH
   969						q.Pcond = q.Link.Link
   970						bflag = 1
   971					}
   972				}
   973				m = int(o.size)
   974	
   975				if m == 0 {
   976					if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
   977						c.ctxt.Diag("zero-width instruction\n%v", p)
   978					}
   979					continue
   980				}
   981	
   982				pc += int64(m)
   983			}
   984		}
   985	
   986		pc += -pc & (funcAlign - 1)
   987		c.cursym.Size = pc
   988	
   989		/*
   990		 * lay out the code, emitting code and data relocations.
   991		 */
   992		c.cursym.Grow(c.cursym.Size)
   993		bp := c.cursym.P
   994		psz := int32(0)
   995		var i int
   996		var out [6]uint32
   997		for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
   998			c.pc = p.Pc
   999			o = c.oplook(p)
  1000	
  1001			// need to align DWORDs on 8-byte boundary. The ISA doesn't
  1002			// require it, but the various 64-bit loads we generate assume it.
  1003			if o.as == ADWORD && psz%8 != 0 {
  1004				bp[3] = 0
  1005				bp[2] = bp[3]
  1006				bp[1] = bp[2]
  1007				bp[0] = bp[1]
  1008				bp = bp[4:]
  1009				psz += 4
  1010			}
  1011	
  1012			if int(o.size) > 4*len(out) {
  1013				log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
  1014			}
  1015			c.asmout(p, o, out[:])
  1016			for i = 0; i < int(o.size/4); i++ {
  1017				c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
  1018				bp = bp[4:]
  1019				psz += 4
  1020			}
  1021		}
  1022	}
  1023	
  1024	/*
  1025	 * when the first reference to the literal pool threatens
  1026	 * to go out of range of a 1Mb PC-relative offset
  1027	 * drop the pool now, and branch round it.
  1028	 */
  1029	func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
  1030		if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
  1031			c.flushpool(p, skip)
  1032		} else if p.Link == nil {
  1033			c.flushpool(p, 2)
  1034		}
  1035	}
  1036	
  1037	func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
  1038		if c.blitrl != nil {
  1039			if skip != 0 {
  1040				if c.ctxt.Debugvlog && skip == 1 {
  1041					fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
  1042				}
  1043				q := c.newprog()
  1044				q.As = AB
  1045				q.To.Type = obj.TYPE_BRANCH
  1046				q.Pcond = p.Link
  1047				q.Link = c.blitrl
  1048				q.Pos = p.Pos
  1049				c.blitrl = q
  1050			} else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
  1051				return
  1052			}
  1053	
  1054			// The line number for constant pool entries doesn't really matter.
  1055			// We set it to the line number of the preceding instruction so that
  1056			// there are no deltas to encode in the pc-line tables.
  1057			for q := c.blitrl; q != nil; q = q.Link {
  1058				q.Pos = p.Pos
  1059			}
  1060	
  1061			c.elitrl.Link = p.Link
  1062			p.Link = c.blitrl
  1063	
  1064			c.blitrl = nil /* BUG: should refer back to values until out-of-range */
  1065			c.elitrl = nil
  1066			c.pool.size = 0
  1067			c.pool.start = 0
  1068		}
  1069	}
  1070	
  1071	/*
  1072	 * MOVD foo(SB), R is actually
  1073	 *   MOVD addr, REGTMP
  1074	 *   MOVD REGTMP, R
  1075	 * where addr is the address of the DWORD containing the address of foo.
  1076	 *
  1077	 * TODO: hash
  1078	 */
  1079	func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
  1080		cls := c.aclass(a)
  1081		lit := c.instoffset
  1082		t := c.newprog()
  1083		t.As = AWORD
  1084		sz := 4
  1085	
  1086		if a.Type == obj.TYPE_CONST {
  1087			if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
  1088				// out of range -0x80000000 ~ 0xffffffff, must store 64-bit
  1089				t.As = ADWORD
  1090				sz = 8
  1091			} // else store 32-bit
  1092		} else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) {
  1093			// conservative: don't know if we want signed or unsigned extension.
  1094			// in case of ambiguity, store 64-bit
  1095			t.As = ADWORD
  1096			sz = 8
  1097		}
  1098	
  1099		switch cls {
  1100		// TODO(aram): remove.
  1101		default:
  1102			if a.Name != obj.NAME_EXTERN {
  1103				fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p)
  1104			}
  1105	
  1106			t.To.Offset = a.Offset
  1107			t.To.Sym = a.Sym
  1108			t.To.Type = a.Type
  1109			t.To.Name = a.Name
  1110	
  1111		/* This is here because MOV uint12<<12, R is disabled in optab.
  1112		Because of this, we need to load the constant from memory. */
  1113		case C_ADDCON:
  1114			fallthrough
  1115	
  1116		case C_ZAUTO,
  1117			C_PSAUTO,
  1118			C_PSAUTO_8,
  1119			C_PSAUTO_4,
  1120			C_PPAUTO,
  1121			C_UAUTO4K_8,
  1122			C_UAUTO4K_4,
  1123			C_UAUTO4K_2,
  1124			C_UAUTO4K,
  1125			C_UAUTO8K_8,
  1126			C_UAUTO8K_4,
  1127			C_UAUTO8K,
  1128			C_UAUTO16K_8,
  1129			C_UAUTO16K,
  1130			C_UAUTO32K,
  1131			C_NSAUTO_8,
  1132			C_NSAUTO_4,
  1133			C_NSAUTO,
  1134			C_NPAUTO,
  1135			C_NAUTO4K,
  1136			C_LAUTO,
  1137			C_PPOREG,
  1138			C_PSOREG,
  1139			C_PSOREG_4,
  1140			C_PSOREG_8,
  1141			C_UOREG4K_8,
  1142			C_UOREG4K_4,
  1143			C_UOREG4K_2,
  1144			C_UOREG4K,
  1145			C_UOREG8K_8,
  1146			C_UOREG8K_4,
  1147			C_UOREG8K,
  1148			C_UOREG16K_8,
  1149			C_UOREG16K,
  1150			C_UOREG32K,
  1151			C_NSOREG_8,
  1152			C_NSOREG_4,
  1153			C_NSOREG,
  1154			C_NPOREG,
  1155			C_NOREG4K,
  1156			C_LOREG,
  1157			C_LACON,
  1158			C_ADDCON2,
  1159			C_LCON,
  1160			C_VCON:
  1161			if a.Name == obj.NAME_EXTERN {
  1162				fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p)
  1163			}
  1164	
  1165			t.To.Type = obj.TYPE_CONST
  1166			t.To.Offset = lit
  1167			break
  1168		}
  1169	
  1170		for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
  1171			if q.To == t.To {
  1172				p.Pcond = q
  1173				return
  1174			}
  1175		}
  1176	
  1177		q := c.newprog()
  1178		*q = *t
  1179		q.Pc = int64(c.pool.size)
  1180		if c.blitrl == nil {
  1181			c.blitrl = q
  1182			c.pool.start = uint32(p.Pc)
  1183		} else {
  1184			c.elitrl.Link = q
  1185		}
  1186		c.elitrl = q
  1187		c.pool.size = -c.pool.size & (funcAlign - 1)
  1188		c.pool.size += uint32(sz)
  1189		p.Pcond = q
  1190	}
  1191	
  1192	func (c *ctxt7) regoff(a *obj.Addr) uint32 {
  1193		c.instoffset = 0
  1194		c.aclass(a)
  1195		return uint32(c.instoffset)
  1196	}
  1197	
  1198	func isSTLXRop(op obj.As) bool {
  1199		switch op {
  1200		case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
  1201			ASTXR, ASTXRW, ASTXRB, ASTXRH:
  1202			return true
  1203		}
  1204		return false
  1205	}
  1206	
  1207	func isSTXPop(op obj.As) bool {
  1208		switch op {
  1209		case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
  1210			return true
  1211		}
  1212		return false
  1213	}
  1214	
  1215	func isANDop(op obj.As) bool {
  1216		switch op {
  1217		case AAND, AORR, AEOR, AANDS, ATST,
  1218			ABIC, AEON, AORN, ABICS:
  1219			return true
  1220		}
  1221		return false
  1222	}
  1223	
  1224	func isANDWop(op obj.As) bool {
  1225		switch op {
  1226		case AANDW, AORRW, AEORW, AANDSW, ATSTW,
  1227			ABICW, AEONW, AORNW, ABICSW:
  1228			return true
  1229		}
  1230		return false
  1231	}
  1232	
  1233	func isADDop(op obj.As) bool {
  1234		switch op {
  1235		case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
  1236			return true
  1237		}
  1238		return false
  1239	}
  1240	
  1241	func isADDWop(op obj.As) bool {
  1242		switch op {
  1243		case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
  1244			return true
  1245		}
  1246		return false
  1247	}
  1248	
  1249	func isRegShiftOrExt(a *obj.Addr) bool {
  1250		return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
  1251	}
  1252	
  1253	// Maximum PC-relative displacement.
  1254	// The actual limit is ±2²⁰, but we are conservative
  1255	// to avoid needing to recompute the literal pool flush points
  1256	// as span-dependent jumps are enlarged.
  1257	const maxPCDisp = 512 * 1024
  1258	
  1259	// ispcdisp reports whether v is a valid PC-relative displacement.
  1260	func ispcdisp(v int32) bool {
  1261		return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
  1262	}
  1263	
  1264	func isaddcon(v int64) bool {
  1265		/* uimm12 or uimm24? */
  1266		if v < 0 {
  1267			return false
  1268		}
  1269		if (v & 0xFFF) == 0 {
  1270			v >>= 12
  1271		}
  1272		return v <= 0xFFF
  1273	}
  1274	
  1275	// isbitcon reports whether a constant can be encoded into a logical instruction.
  1276	// bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
  1277	// which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
  1278	// special cases: 0 and -1 are not bitcon.
  1279	// this function needs to run against virtually all the constants, so it needs to be fast.
  1280	// for this reason, bitcon testing and bitcon encoding are separate functions.
  1281	func isbitcon(x uint64) bool {
  1282		if x == 1<<64-1 || x == 0 {
  1283			return false
  1284		}
  1285		// determine the period and sign-extend a unit to 64 bits
  1286		switch {
  1287		case x != x>>32|x<<32:
  1288			// period is 64
  1289			// nothing to do
  1290		case x != x>>16|x<<48:
  1291			// period is 32
  1292			x = uint64(int64(int32(x)))
  1293		case x != x>>8|x<<56:
  1294			// period is 16
  1295			x = uint64(int64(int16(x)))
  1296		case x != x>>4|x<<60:
  1297			// period is 8
  1298			x = uint64(int64(int8(x)))
  1299		default:
  1300			// period is 4 or 2, always true
  1301			// 0001, 0010, 0100, 1000 -- 0001 rotate
  1302			// 0011, 0110, 1100, 1001 -- 0011 rotate
  1303			// 0111, 1011, 1101, 1110 -- 0111 rotate
  1304			// 0101, 1010             -- 01   rotate, repeat
  1305			return true
  1306		}
  1307		return sequenceOfOnes(x) || sequenceOfOnes(^x)
  1308	}
  1309	
  1310	// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
  1311	func sequenceOfOnes(x uint64) bool {
  1312		y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
  1313		y += x
  1314		return (y-1)&y == 0
  1315	}
  1316	
  1317	// bitconEncode returns the encoding of a bitcon used in logical instructions
  1318	// x is known to be a bitcon
  1319	// a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
  1320	// by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
  1321	// it is encoded in logical instructions with 3 bitfields
  1322	// N (1 bit) : R (6 bits) : S (6 bits), where
  1323	// N=1           -- period=64
  1324	// N=0, S=0xxxxx -- period=32
  1325	// N=0, S=10xxxx -- period=16
  1326	// N=0, S=110xxx -- period=8
  1327	// N=0, S=1110xx -- period=4
  1328	// N=0, S=11110x -- period=2
  1329	// R is the shift amount, low bits of S = n-1
  1330	func bitconEncode(x uint64, mode int) uint32 {
  1331		var period uint32
  1332		// determine the period and sign-extend a unit to 64 bits
  1333		switch {
  1334		case x != x>>32|x<<32:
  1335			period = 64
  1336		case x != x>>16|x<<48:
  1337			period = 32
  1338			x = uint64(int64(int32(x)))
  1339		case x != x>>8|x<<56:
  1340			period = 16
  1341			x = uint64(int64(int16(x)))
  1342		case x != x>>4|x<<60:
  1343			period = 8
  1344			x = uint64(int64(int8(x)))
  1345		case x != x>>2|x<<62:
  1346			period = 4
  1347			x = uint64(int64(x<<60) >> 60)
  1348		default:
  1349			period = 2
  1350			x = uint64(int64(x<<62) >> 62)
  1351		}
  1352		neg := false
  1353		if int64(x) < 0 {
  1354			x = ^x
  1355			neg = true
  1356		}
  1357		y := x & -x // lowest set bit of x.
  1358		s := log2(y)
  1359		n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
  1360		if neg {
  1361			// ^x is a sequence of n ones left shifted by s bits
  1362			// adjust n, s for x
  1363			s = n + s
  1364			n = period - n
  1365		}
  1366	
  1367		N := uint32(0)
  1368		if mode == 64 && period == 64 {
  1369			N = 1
  1370		}
  1371		R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
  1372		S := (n - 1) | 63&^(period<<1-1)                  // low bits = #ones - 1, high bits encodes period
  1373		return N<<22 | R<<16 | S<<10
  1374	}
  1375	
  1376	func log2(x uint64) uint32 {
  1377		if x == 0 {
  1378			panic("log2 of 0")
  1379		}
  1380		n := uint32(0)
  1381		if x >= 1<<32 {
  1382			x >>= 32
  1383			n += 32
  1384		}
  1385		if x >= 1<<16 {
  1386			x >>= 16
  1387			n += 16
  1388		}
  1389		if x >= 1<<8 {
  1390			x >>= 8
  1391			n += 8
  1392		}
  1393		if x >= 1<<4 {
  1394			x >>= 4
  1395			n += 4
  1396		}
  1397		if x >= 1<<2 {
  1398			x >>= 2
  1399			n += 2
  1400		}
  1401		if x >= 1<<1 {
  1402			x >>= 1
  1403			n += 1
  1404		}
  1405		return n
  1406	}
  1407	
  1408	func autoclass(l int64) int {
  1409		if l == 0 {
  1410			return C_ZAUTO
  1411		}
  1412	
  1413		if l < 0 {
  1414			if l >= -256 && (l&7) == 0 {
  1415				return C_NSAUTO_8
  1416			}
  1417			if l >= -256 && (l&3) == 0 {
  1418				return C_NSAUTO_4
  1419			}
  1420			if l >= -256 {
  1421				return C_NSAUTO
  1422			}
  1423			if l >= -512 && (l&7) == 0 {
  1424				return C_NPAUTO
  1425			}
  1426			if l >= -4095 {
  1427				return C_NAUTO4K
  1428			}
  1429			return C_LAUTO
  1430		}
  1431	
  1432		if l <= 255 {
  1433			if (l & 7) == 0 {
  1434				return C_PSAUTO_8
  1435			}
  1436			if (l & 3) == 0 {
  1437				return C_PSAUTO_4
  1438			}
  1439			return C_PSAUTO
  1440		}
  1441		if l <= 504 && l&7 == 0 {
  1442			return C_PPAUTO
  1443		}
  1444		if l <= 4095 {
  1445			if l&7 == 0 {
  1446				return C_UAUTO4K_8
  1447			}
  1448			if l&3 == 0 {
  1449				return C_UAUTO4K_4
  1450			}
  1451			if l&1 == 0 {
  1452				return C_UAUTO4K_2
  1453			}
  1454			return C_UAUTO4K
  1455		}
  1456		if l <= 8190 {
  1457			if l&7 == 0 {
  1458				return C_UAUTO8K_8
  1459			}
  1460			if l&3 == 0 {
  1461				return C_UAUTO8K_4
  1462			}
  1463			if l&1 == 0 {
  1464				return C_UAUTO8K
  1465			}
  1466		}
  1467		if l <= 16380 {
  1468			if l&7 == 0 {
  1469				return C_UAUTO16K_8
  1470			}
  1471			if l&3 == 0 {
  1472				return C_UAUTO16K
  1473			}
  1474		}
  1475		if l <= 32760 && (l&7) == 0 {
  1476			return C_UAUTO32K
  1477		}
  1478		return C_LAUTO
  1479	}
  1480	
  1481	func oregclass(l int64) int {
  1482		return autoclass(l) - C_ZAUTO + C_ZOREG
  1483	}
  1484	
  1485	/*
  1486	 * given an offset v and a class c (see above)
  1487	 * return the offset value to use in the instruction,
  1488	 * scaled if necessary
  1489	 */
  1490	func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
  1491		s := 0
  1492		if cls >= C_SEXT1 && cls <= C_SEXT16 {
  1493			s = cls - C_SEXT1
  1494		} else {
  1495			switch cls {
  1496			case C_UAUTO4K, C_UOREG4K, C_ZOREG:
  1497				s = 0
  1498			case C_UAUTO8K, C_UOREG8K:
  1499				s = 1
  1500			case C_UAUTO16K, C_UOREG16K:
  1501				s = 2
  1502			case C_UAUTO32K, C_UOREG32K:
  1503				s = 3
  1504			default:
  1505				c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
  1506			}
  1507		}
  1508		vs := v >> uint(s)
  1509		if vs<<uint(s) != v {
  1510			c.ctxt.Diag("odd offset: %d\n%v", v, p)
  1511		}
  1512		return vs
  1513	}
  1514	
  1515	/*
  1516	 * if v contains a single 16-bit value aligned
  1517	 * on a 16-bit field, and thus suitable for movk/movn,
  1518	 * return the field index 0 to 3; otherwise return -1
  1519	 */
  1520	func movcon(v int64) int {
  1521		for s := 0; s < 64; s += 16 {
  1522			if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
  1523				return s / 16
  1524			}
  1525		}
  1526		return -1
  1527	}
  1528	
  1529	func rclass(r int16) int {
  1530		switch {
  1531		case REG_R0 <= r && r <= REG_R30: // not 31
  1532			return C_REG
  1533		case r == REGZERO:
  1534			return C_ZCON
  1535		case REG_F0 <= r && r <= REG_F31:
  1536			return C_FREG
  1537		case REG_V0 <= r && r <= REG_V31:
  1538			return C_VREG
  1539		case COND_EQ <= r && r <= COND_NV:
  1540			return C_COND
  1541		case r == REGSP:
  1542			return C_RSP
  1543		case r >= REG_ARNG && r < REG_ELEM:
  1544			return C_ARNG
  1545		case r >= REG_ELEM && r < REG_ELEM_END:
  1546			return C_ELEM
  1547		case r >= REG_UXTB && r < REG_SPECIAL:
  1548			return C_EXTREG
  1549		case r >= REG_SPECIAL:
  1550			return C_SPR
  1551		}
  1552		return C_GOK
  1553	}
  1554	
  1555	// con32class reclassifies the constant of 32-bit instruction. Becuase the constant type is 32-bit,
  1556	// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
  1557	func (c *ctxt7) con32class(a *obj.Addr) int {
  1558		v := uint32(a.Offset)
  1559		if v == 0 {
  1560			return C_ZCON
  1561		}
  1562		if isaddcon(int64(v)) {
  1563			if v <= 0xFFF {
  1564				if isbitcon(uint64(v)) {
  1565					return C_ABCON0
  1566				}
  1567				return C_ADDCON0
  1568			}
  1569			if isbitcon(uint64(v)) {
  1570				return C_ABCON
  1571			}
  1572			if movcon(int64(v)) >= 0 {
  1573				return C_AMCON
  1574			}
  1575			if movcon(int64(^v)) >= 0 {
  1576				return C_AMCON
  1577			}
  1578			return C_ADDCON
  1579		}
  1580	
  1581		t := movcon(int64(v))
  1582		if t >= 0 {
  1583			if isbitcon(uint64(v)) {
  1584				return C_MBCON
  1585			}
  1586			return C_MOVCON
  1587		}
  1588	
  1589		t = movcon(int64(^v))
  1590		if t >= 0 {
  1591			if isbitcon(uint64(v)) {
  1592				return C_MBCON
  1593			}
  1594			return C_MOVCON
  1595		}
  1596	
  1597		if isbitcon(uint64(v)) {
  1598			return C_BITCON
  1599		}
  1600	
  1601		if 0 <= v && v <= 0xffffff {
  1602			return C_ADDCON2
  1603		}
  1604		return C_LCON
  1605	}
  1606	
  1607	// con64class reclassifies the constant of C_VCON and C_LCON class.
  1608	func (c *ctxt7) con64class(a *obj.Addr) int {
  1609		zeroCount := 0
  1610		negCount := 0
  1611		for i := uint(0); i < 4; i++ {
  1612			immh := uint32(a.Offset >> (i * 16) & 0xffff)
  1613			if immh == 0 {
  1614				zeroCount++
  1615			} else if immh == 0xffff {
  1616				negCount++
  1617			}
  1618		}
  1619		if zeroCount >= 3 || negCount >= 3 {
  1620			return C_MOVCON
  1621		} else if zeroCount == 2 || negCount == 2 {
  1622			return C_MOVCON2
  1623		} else if zeroCount == 1 || negCount == 1 {
  1624			return C_MOVCON3
  1625		} else {
  1626			return C_VCON
  1627		}
  1628	}
  1629	
  1630	func (c *ctxt7) aclass(a *obj.Addr) int {
  1631		switch a.Type {
  1632		case obj.TYPE_NONE:
  1633			return C_NONE
  1634	
  1635		case obj.TYPE_REG:
  1636			return rclass(a.Reg)
  1637	
  1638		case obj.TYPE_REGREG:
  1639			return C_PAIR
  1640	
  1641		case obj.TYPE_SHIFT:
  1642			return C_SHIFT
  1643	
  1644		case obj.TYPE_REGLIST:
  1645			return C_LIST
  1646	
  1647		case obj.TYPE_MEM:
  1648			// The base register should be an integer register.
  1649			if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
  1650				break
  1651			}
  1652			switch a.Name {
  1653			case obj.NAME_EXTERN, obj.NAME_STATIC:
  1654				if a.Sym == nil {
  1655					break
  1656				}
  1657				c.instoffset = a.Offset
  1658				if a.Sym != nil { // use relocation
  1659					if a.Sym.Type == objabi.STLSBSS {
  1660						if c.ctxt.Flag_shared {
  1661							return C_TLS_IE
  1662						} else {
  1663							return C_TLS_LE
  1664						}
  1665					}
  1666					return C_ADDR
  1667				}
  1668				return C_LEXT
  1669	
  1670			case obj.NAME_GOTREF:
  1671				return C_GOTADDR
  1672	
  1673			case obj.NAME_AUTO:
  1674				if a.Reg == REGSP {
  1675					// unset base register for better printing, since
  1676					// a.Offset is still relative to pseudo-SP.
  1677					a.Reg = obj.REG_NONE
  1678				}
  1679				// The frame top 8 or 16 bytes are for FP
  1680				c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1681				return autoclass(c.instoffset)
  1682	
  1683			case obj.NAME_PARAM:
  1684				if a.Reg == REGSP {
  1685					// unset base register for better printing, since
  1686					// a.Offset is still relative to pseudo-FP.
  1687					a.Reg = obj.REG_NONE
  1688				}
  1689				c.instoffset = int64(c.autosize) + a.Offset + 8
  1690				return autoclass(c.instoffset)
  1691	
  1692			case obj.NAME_NONE:
  1693				if a.Index != 0 {
  1694					if a.Offset != 0 {
  1695						if isRegShiftOrExt(a) {
  1696							// extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
  1697							return C_ROFF
  1698						}
  1699						return C_GOK
  1700					}
  1701					// register offset, (Rn)(Rm)
  1702					return C_ROFF
  1703				}
  1704				c.instoffset = a.Offset
  1705				return oregclass(c.instoffset)
  1706			}
  1707			return C_GOK
  1708	
  1709		case obj.TYPE_FCONST:
  1710			return C_FCON
  1711	
  1712		case obj.TYPE_TEXTSIZE:
  1713			return C_TEXTSIZE
  1714	
  1715		case obj.TYPE_CONST, obj.TYPE_ADDR:
  1716			switch a.Name {
  1717			case obj.NAME_NONE:
  1718				c.instoffset = a.Offset
  1719				if a.Reg != 0 && a.Reg != REGZERO {
  1720					break
  1721				}
  1722				v := c.instoffset
  1723				if v == 0 {
  1724					return C_ZCON
  1725				}
  1726				if isaddcon(v) {
  1727					if v <= 0xFFF {
  1728						if isbitcon(uint64(v)) {
  1729							return C_ABCON0
  1730						}
  1731						return C_ADDCON0
  1732					}
  1733					if isbitcon(uint64(v)) {
  1734						return C_ABCON
  1735					}
  1736					if movcon(v) >= 0 {
  1737						return C_AMCON
  1738					}
  1739					if movcon(^v) >= 0 {
  1740						return C_AMCON
  1741					}
  1742					return C_ADDCON
  1743				}
  1744	
  1745				t := movcon(v)
  1746				if t >= 0 {
  1747					if isbitcon(uint64(v)) {
  1748						return C_MBCON
  1749					}
  1750					return C_MOVCON
  1751				}
  1752	
  1753				t = movcon(^v)
  1754				if t >= 0 {
  1755					if isbitcon(uint64(v)) {
  1756						return C_MBCON
  1757					}
  1758					return C_MOVCON
  1759				}
  1760	
  1761				if isbitcon(uint64(v)) {
  1762					return C_BITCON
  1763				}
  1764	
  1765				if 0 <= v && v <= 0xffffff {
  1766					return C_ADDCON2
  1767				}
  1768	
  1769				if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
  1770					return C_LCON
  1771				}
  1772				return C_VCON
  1773	
  1774			case obj.NAME_EXTERN, obj.NAME_STATIC:
  1775				if a.Sym == nil {
  1776					return C_GOK
  1777				}
  1778				if a.Sym.Type == objabi.STLSBSS {
  1779					c.ctxt.Diag("taking address of TLS variable is not supported")
  1780				}
  1781				c.instoffset = a.Offset
  1782				return C_VCONADDR
  1783	
  1784			case obj.NAME_AUTO:
  1785				if a.Reg == REGSP {
  1786					// unset base register for better printing, since
  1787					// a.Offset is still relative to pseudo-SP.
  1788					a.Reg = obj.REG_NONE
  1789				}
  1790				// The frame top 8 or 16 bytes are for FP
  1791				c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1792	
  1793			case obj.NAME_PARAM:
  1794				if a.Reg == REGSP {
  1795					// unset base register for better printing, since
  1796					// a.Offset is still relative to pseudo-FP.
  1797					a.Reg = obj.REG_NONE
  1798				}
  1799				c.instoffset = int64(c.autosize) + a.Offset + 8
  1800			default:
  1801				return C_GOK
  1802			}
  1803	
  1804			if isaddcon(c.instoffset) {
  1805				return C_AACON
  1806			}
  1807			return C_LACON
  1808	
  1809		case obj.TYPE_BRANCH:
  1810			return C_SBRA
  1811		}
  1812	
  1813		return C_GOK
  1814	}
  1815	
  1816	func oclass(a *obj.Addr) int {
  1817		return int(a.Class) - 1
  1818	}
  1819	
  1820	func (c *ctxt7) oplook(p *obj.Prog) *Optab {
  1821		a1 := int(p.Optab)
  1822		if a1 != 0 {
  1823			return &optab[a1-1]
  1824		}
  1825		a1 = int(p.From.Class)
  1826		if a1 == 0 {
  1827			a0 := c.aclass(&p.From)
  1828			// do not break C_ADDCON2 when S bit is set
  1829			if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
  1830				a0 = C_LCON
  1831			}
  1832			a1 = a0 + 1
  1833			p.From.Class = int8(a1)
  1834			// more specific classification of 32-bit integers
  1835			if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
  1836				if p.As == AMOVW || isADDWop(p.As) {
  1837					ra0 := c.con32class(&p.From)
  1838					// do not break C_ADDCON2 when S bit is set
  1839					if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
  1840						ra0 = C_LCON
  1841					}
  1842					a1 = ra0 + 1
  1843					p.From.Class = int8(a1)
  1844				}
  1845				if isANDWop(p.As) && a0 != C_BITCON {
  1846					// For 32-bit logical instruction with constant,
  1847					// the BITCON test is special in that it looks at
  1848					// the 64-bit which has the high 32-bit as a copy
  1849					// of the low 32-bit. We have handled that and
  1850					// don't pass it to con32class.
  1851					a1 = c.con32class(&p.From) + 1
  1852					p.From.Class = int8(a1)
  1853				}
  1854				if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
  1855					a1 = c.con64class(&p.From) + 1
  1856					p.From.Class = int8(a1)
  1857				}
  1858			}
  1859		}
  1860	
  1861		a1--
  1862		a3 := C_NONE + 1
  1863		if p.GetFrom3() != nil {
  1864			a3 = int(p.GetFrom3().Class)
  1865			if a3 == 0 {
  1866				a3 = c.aclass(p.GetFrom3()) + 1
  1867				p.GetFrom3().Class = int8(a3)
  1868			}
  1869		}
  1870	
  1871		a3--
  1872		a4 := int(p.To.Class)
  1873		if a4 == 0 {
  1874			a4 = c.aclass(&p.To) + 1
  1875			p.To.Class = int8(a4)
  1876		}
  1877	
  1878		a4--
  1879		a2 := C_NONE
  1880		if p.Reg != 0 {
  1881			a2 = rclass(p.Reg)
  1882		}
  1883	
  1884		if false {
  1885			fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
  1886			fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  1887		}
  1888	
  1889		ops := oprange[p.As&obj.AMask]
  1890		c1 := &xcmp[a1]
  1891		c2 := &xcmp[a2]
  1892		c3 := &xcmp[a3]
  1893		c4 := &xcmp[a4]
  1894		c5 := &xcmp[p.Scond>>5]
  1895		for i := range ops {
  1896			op := &ops[i]
  1897			if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
  1898				p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1899				return op
  1900			}
  1901		}
  1902	
  1903		c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type)
  1904		// Turn illegal instruction into an UNDEF, avoid crashing in asmout
  1905		return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
  1906	}
  1907	
  1908	func cmp(a int, b int) bool {
  1909		if a == b {
  1910			return true
  1911		}
  1912		switch a {
  1913		case C_RSP:
  1914			if b == C_REG {
  1915				return true
  1916			}
  1917	
  1918		case C_REG:
  1919			if b == C_ZCON {
  1920				return true
  1921			}
  1922	
  1923		case C_ADDCON0:
  1924			if b == C_ZCON || b == C_ABCON0 {
  1925				return true
  1926			}
  1927	
  1928		case C_ADDCON:
  1929			if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
  1930				return true
  1931			}
  1932	
  1933		case C_BITCON:
  1934			if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
  1935				return true
  1936			}
  1937	
  1938		case C_MOVCON:
  1939			if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
  1940				return true
  1941			}
  1942	
  1943		case C_ADDCON2:
  1944			if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
  1945				return true
  1946			}
  1947	
  1948		case C_LCON:
  1949			if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
  1950				return true
  1951			}
  1952	
  1953		case C_MOVCON2:
  1954			return cmp(C_LCON, b)
  1955	
  1956		case C_VCON:
  1957			return cmp(C_LCON, b)
  1958	
  1959		case C_LACON:
  1960			if b == C_AACON {
  1961				return true
  1962			}
  1963	
  1964		case C_SEXT2:
  1965			if b == C_SEXT1 {
  1966				return true
  1967			}
  1968	
  1969		case C_SEXT4:
  1970			if b == C_SEXT1 || b == C_SEXT2 {
  1971				return true
  1972			}
  1973	
  1974		case C_SEXT8:
  1975			if b >= C_SEXT1 && b <= C_SEXT4 {
  1976				return true
  1977			}
  1978	
  1979		case C_SEXT16:
  1980			if b >= C_SEXT1 && b <= C_SEXT8 {
  1981				return true
  1982			}
  1983	
  1984		case C_LEXT:
  1985			if b >= C_SEXT1 && b <= C_SEXT16 {
  1986				return true
  1987			}
  1988	
  1989		case C_NSAUTO_4:
  1990			if b == C_NSAUTO_8 {
  1991				return true
  1992			}
  1993	
  1994		case C_NSAUTO:
  1995			switch b {
  1996			case C_NSAUTO_4, C_NSAUTO_8:
  1997				return true
  1998			}
  1999	
  2000		case C_NPAUTO:
  2001			switch b {
  2002			case C_NSAUTO_8:
  2003				return true
  2004			}
  2005	
  2006		case C_NAUTO4K:
  2007			switch b {
  2008			case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO:
  2009				return true
  2010			}
  2011	
  2012		case C_PSAUTO_8:
  2013			if b == C_ZAUTO {
  2014				return true
  2015			}
  2016	
  2017		case C_PSAUTO_4:
  2018			switch b {
  2019			case C_ZAUTO, C_PSAUTO_8:
  2020				return true
  2021			}
  2022	
  2023		case C_PSAUTO:
  2024			switch b {
  2025			case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4:
  2026				return true
  2027			}
  2028	
  2029		case C_PPAUTO:
  2030			switch b {
  2031			case C_ZAUTO, C_PSAUTO_8:
  2032				return true
  2033			}
  2034	
  2035		case C_UAUTO4K:
  2036			switch b {
  2037			case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
  2038				C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
  2039				return true
  2040			}
  2041	
  2042		case C_UAUTO8K:
  2043			switch b {
  2044			case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  2045				C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
  2046				return true
  2047			}
  2048	
  2049		case C_UAUTO16K:
  2050			switch b {
  2051			case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  2052				C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
  2053				return true
  2054			}
  2055	
  2056		case C_UAUTO32K:
  2057			switch b {
  2058			case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
  2059				C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
  2060				return true
  2061			}
  2062	
  2063		case C_LAUTO:
  2064			switch b {
  2065			case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO,
  2066				C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  2067				C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
  2068				C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
  2069				C_UAUTO16K, C_UAUTO16K_8,
  2070				C_UAUTO32K:
  2071				return true
  2072			}
  2073	
  2074		case C_NSOREG_4:
  2075			if b == C_NSOREG_8 {
  2076				return true
  2077			}
  2078	
  2079		case C_NSOREG:
  2080			switch b {
  2081			case C_NSOREG_4, C_NSOREG_8:
  2082				return true
  2083			}
  2084	
  2085		case C_NPOREG:
  2086			switch b {
  2087			case C_NSOREG_8:
  2088				return true
  2089			}
  2090	
  2091		case C_NOREG4K:
  2092			switch b {
  2093			case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG:
  2094				return true
  2095			}
  2096	
  2097		case C_PSOREG_4:
  2098			switch b {
  2099			case C_ZOREG, C_PSOREG_8:
  2100				return true
  2101			}
  2102	
  2103		case C_PSOREG:
  2104			switch b {
  2105			case C_ZOREG, C_PSOREG_8, C_PSOREG_4:
  2106				return true
  2107			}
  2108	
  2109		case C_PPOREG:
  2110			switch b {
  2111			case C_ZOREG, C_PSOREG_8:
  2112				return true
  2113			}
  2114	
  2115		case C_UOREG4K:
  2116			switch b {
  2117			case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2118				C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8:
  2119				return true
  2120			}
  2121	
  2122		case C_UOREG8K:
  2123			switch b {
  2124			case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2125				C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
  2126				C_UOREG8K_4, C_UOREG8K_8:
  2127				return true
  2128			}
  2129	
  2130		case C_UOREG16K:
  2131			switch b {
  2132			case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2133				C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4,
  2134				C_UOREG8K_8, C_UOREG16K_8:
  2135				return true
  2136			}
  2137	
  2138		case C_UOREG32K:
  2139			switch b {
  2140			case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2141				C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8:
  2142				return true
  2143			}
  2144	
  2145		case C_LOREG:
  2146			switch b {
  2147			case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG,
  2148				C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG,
  2149				C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
  2150				C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8,
  2151				C_UOREG16K, C_UOREG16K_8,
  2152				C_UOREG32K:
  2153				return true
  2154			}
  2155	
  2156		case C_LBRA:
  2157			if b == C_SBRA {
  2158				return true
  2159			}
  2160		}
  2161	
  2162		return false
  2163	}
  2164	
  2165	type ocmp []Optab
  2166	
  2167	func (x ocmp) Len() int {
  2168		return len(x)
  2169	}
  2170	
  2171	func (x ocmp) Swap(i, j int) {
  2172		x[i], x[j] = x[j], x[i]
  2173	}
  2174	
  2175	func (x ocmp) Less(i, j int) bool {
  2176		p1 := &x[i]
  2177		p2 := &x[j]
  2178		if p1.as != p2.as {
  2179			return p1.as < p2.as
  2180		}
  2181		if p1.a1 != p2.a1 {
  2182			return p1.a1 < p2.a1
  2183		}
  2184		if p1.a2 != p2.a2 {
  2185			return p1.a2 < p2.a2
  2186		}
  2187		if p1.a3 != p2.a3 {
  2188			return p1.a3 < p2.a3
  2189		}
  2190		if p1.a4 != p2.a4 {
  2191			return p1.a4 < p2.a4
  2192		}
  2193		if p1.scond != p2.scond {
  2194			return p1.scond < p2.scond
  2195		}
  2196		return false
  2197	}
  2198	
  2199	func oprangeset(a obj.As, t []Optab) {
  2200		oprange[a&obj.AMask] = t
  2201	}
  2202	
  2203	func buildop(ctxt *obj.Link) {
  2204		if oprange[AAND&obj.AMask] != nil {
  2205			// Already initialized; stop now.
  2206			// This happens in the cmd/asm tests,
  2207			// each of which re-initializes the arch.
  2208			return
  2209		}
  2210	
  2211		var n int
  2212		for i := 0; i < C_GOK; i++ {
  2213			for n = 0; n < C_GOK; n++ {
  2214				if cmp(n, i) {
  2215					xcmp[i][n] = true
  2216				}
  2217			}
  2218		}
  2219		for n = 0; optab[n].as != obj.AXXX; n++ {
  2220		}
  2221		sort.Sort(ocmp(optab[:n]))
  2222		for i := 0; i < n; i++ {
  2223			r := optab[i].as
  2224			start := i
  2225			for optab[i].as == r {
  2226				i++
  2227			}
  2228			t := optab[start:i]
  2229			i--
  2230			oprangeset(r, t)
  2231			switch r {
  2232			default:
  2233				ctxt.Diag("unknown op in build: %v", r)
  2234				ctxt.DiagFlush()
  2235				log.Fatalf("bad code")
  2236	
  2237			case AADD:
  2238				oprangeset(AADDS, t)
  2239				oprangeset(ASUB, t)
  2240				oprangeset(ASUBS, t)
  2241				oprangeset(AADDW, t)
  2242				oprangeset(AADDSW, t)
  2243				oprangeset(ASUBW, t)
  2244				oprangeset(ASUBSW, t)
  2245	
  2246			case AAND: /* logical immediate, logical shifted register */
  2247				oprangeset(AANDW, t)
  2248				oprangeset(AEOR, t)
  2249				oprangeset(AEORW, t)
  2250				oprangeset(AORR, t)
  2251				oprangeset(AORRW, t)
  2252				oprangeset(ABIC, t)
  2253				oprangeset(ABICW, t)
  2254				oprangeset(AEON, t)
  2255				oprangeset(AEONW, t)
  2256				oprangeset(AORN, t)
  2257				oprangeset(AORNW, t)
  2258	
  2259			case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
  2260				oprangeset(AANDSW, t)
  2261				oprangeset(ABICS, t)
  2262				oprangeset(ABICSW, t)
  2263	
  2264			case ANEG:
  2265				oprangeset(ANEGS, t)
  2266				oprangeset(ANEGSW, t)
  2267				oprangeset(ANEGW, t)
  2268	
  2269			case AADC: /* rn=Rd */
  2270				oprangeset(AADCW, t)
  2271	
  2272				oprangeset(AADCS, t)
  2273				oprangeset(AADCSW, t)
  2274				oprangeset(ASBC, t)
  2275				oprangeset(ASBCW, t)
  2276				oprangeset(ASBCS, t)
  2277				oprangeset(ASBCSW, t)
  2278	
  2279			case ANGC: /* rn=REGZERO */
  2280				oprangeset(ANGCW, t)
  2281	
  2282				oprangeset(ANGCS, t)
  2283				oprangeset(ANGCSW, t)
  2284	
  2285			case ACMP:
  2286				oprangeset(ACMPW, t)
  2287				oprangeset(ACMN, t)
  2288				oprangeset(ACMNW, t)
  2289	
  2290			case ATST:
  2291				oprangeset(ATSTW, t)
  2292	
  2293				/* register/register, and shifted */
  2294			case AMVN:
  2295				oprangeset(AMVNW, t)
  2296	
  2297			case AMOVK:
  2298				oprangeset(AMOVKW, t)
  2299				oprangeset(AMOVN, t)
  2300				oprangeset(AMOVNW, t)
  2301				oprangeset(AMOVZ, t)
  2302				oprangeset(AMOVZW, t)
  2303	
  2304			case ASWPD:
  2305				for i := range atomicInstructions {
  2306					oprangeset(i, t)
  2307				}
  2308	
  2309			case ABEQ:
  2310				oprangeset(ABNE, t)
  2311				oprangeset(ABCS, t)
  2312				oprangeset(ABHS, t)
  2313				oprangeset(ABCC, t)
  2314				oprangeset(ABLO, t)
  2315				oprangeset(ABMI, t)
  2316				oprangeset(ABPL, t)
  2317				oprangeset(ABVS, t)
  2318				oprangeset(ABVC, t)
  2319				oprangeset(ABHI, t)
  2320				oprangeset(ABLS, t)
  2321				oprangeset(ABGE, t)
  2322				oprangeset(ABLT, t)
  2323				oprangeset(ABGT, t)
  2324				oprangeset(ABLE, t)
  2325	
  2326			case ALSL:
  2327				oprangeset(ALSLW, t)
  2328				oprangeset(ALSR, t)
  2329				oprangeset(ALSRW, t)
  2330				oprangeset(AASR, t)
  2331				oprangeset(AASRW, t)
  2332				oprangeset(AROR, t)
  2333				oprangeset(ARORW, t)
  2334	
  2335			case ACLS:
  2336				oprangeset(ACLSW, t)
  2337				oprangeset(ACLZ, t)
  2338				oprangeset(ACLZW, t)
  2339				oprangeset(ARBIT, t)
  2340				oprangeset(ARBITW, t)
  2341				oprangeset(AREV, t)
  2342				oprangeset(AREVW, t)
  2343				oprangeset(AREV16, t)
  2344				oprangeset(AREV16W, t)
  2345				oprangeset(AREV32, t)
  2346	
  2347			case ASDIV:
  2348				oprangeset(ASDIVW, t)
  2349				oprangeset(AUDIV, t)
  2350				oprangeset(AUDIVW, t)
  2351				oprangeset(ACRC32B, t)
  2352				oprangeset(ACRC32CB, t)
  2353				oprangeset(ACRC32CH, t)
  2354				oprangeset(ACRC32CW, t)
  2355				oprangeset(ACRC32CX, t)
  2356				oprangeset(ACRC32H, t)
  2357				oprangeset(ACRC32W, t)
  2358				oprangeset(ACRC32X, t)
  2359	
  2360			case AMADD:
  2361				oprangeset(AMADDW, t)
  2362				oprangeset(AMSUB, t)
  2363				oprangeset(AMSUBW, t)
  2364				oprangeset(ASMADDL, t)
  2365				oprangeset(ASMSUBL, t)
  2366				oprangeset(AUMADDL, t)
  2367				oprangeset(AUMSUBL, t)
  2368	
  2369			case AREM:
  2370				oprangeset(AREMW, t)
  2371				oprangeset(AUREM, t)
  2372				oprangeset(AUREMW, t)
  2373	
  2374			case AMUL:
  2375				oprangeset(AMULW, t)
  2376				oprangeset(AMNEG, t)
  2377				oprangeset(AMNEGW, t)
  2378				oprangeset(ASMNEGL, t)
  2379				oprangeset(ASMULL, t)
  2380				oprangeset(ASMULH, t)
  2381				oprangeset(AUMNEGL, t)
  2382				oprangeset(AUMULH, t)
  2383				oprangeset(AUMULL, t)
  2384	
  2385			case AMOVB:
  2386				oprangeset(AMOVBU, t)
  2387	
  2388			case AMOVH:
  2389				oprangeset(AMOVHU, t)
  2390	
  2391			case AMOVW:
  2392				oprangeset(AMOVWU, t)
  2393	
  2394			case ABFM:
  2395				oprangeset(ABFMW, t)
  2396				oprangeset(ASBFM, t)
  2397				oprangeset(ASBFMW, t)
  2398				oprangeset(AUBFM, t)
  2399				oprangeset(AUBFMW, t)
  2400	
  2401			case ABFI:
  2402				oprangeset(ABFIW, t)
  2403				oprangeset(ABFXIL, t)
  2404				oprangeset(ABFXILW, t)
  2405				oprangeset(ASBFIZ, t)
  2406				oprangeset(ASBFIZW, t)
  2407				oprangeset(ASBFX, t)
  2408				oprangeset(ASBFXW, t)
  2409				oprangeset(AUBFIZ, t)
  2410				oprangeset(AUBFIZW, t)
  2411				oprangeset(AUBFX, t)
  2412				oprangeset(AUBFXW, t)
  2413	
  2414			case AEXTR:
  2415				oprangeset(AEXTRW, t)
  2416	
  2417			case ASXTB:
  2418				oprangeset(ASXTBW, t)
  2419				oprangeset(ASXTH, t)
  2420				oprangeset(ASXTHW, t)
  2421				oprangeset(ASXTW, t)
  2422				oprangeset(AUXTB, t)
  2423				oprangeset(AUXTH, t)
  2424				oprangeset(AUXTW, t)
  2425				oprangeset(AUXTBW, t)
  2426				oprangeset(AUXTHW, t)
  2427	
  2428			case ACCMN:
  2429				oprangeset(ACCMNW, t)
  2430				oprangeset(ACCMP, t)
  2431				oprangeset(ACCMPW, t)
  2432	
  2433			case ACSEL:
  2434				oprangeset(ACSELW, t)
  2435				oprangeset(ACSINC, t)
  2436				oprangeset(ACSINCW, t)
  2437				oprangeset(ACSINV, t)
  2438				oprangeset(ACSINVW, t)
  2439				oprangeset(ACSNEG, t)
  2440				oprangeset(ACSNEGW, t)
  2441	
  2442			case ACINC:
  2443				// aliases Rm=Rn, !cond
  2444				oprangeset(ACINCW, t)
  2445				oprangeset(ACINV, t)
  2446				oprangeset(ACINVW, t)
  2447				oprangeset(ACNEG, t)
  2448				oprangeset(ACNEGW, t)
  2449	
  2450				// aliases, Rm=Rn=REGZERO, !cond
  2451			case ACSET:
  2452				oprangeset(ACSETW, t)
  2453	
  2454				oprangeset(ACSETM, t)
  2455				oprangeset(ACSETMW, t)
  2456	
  2457			case AMOVD,
  2458				AMOVBU,
  2459				AB,
  2460				ABL,
  2461				AWORD,
  2462				ADWORD,
  2463				obj.ARET,
  2464				obj.ATEXT:
  2465				break
  2466	
  2467			case ALDP:
  2468				oprangeset(AFLDPD, t)
  2469	
  2470			case ASTP:
  2471				oprangeset(AFSTPD, t)
  2472	
  2473			case ASTPW:
  2474				oprangeset(AFSTPS, t)
  2475	
  2476			case ALDPW:
  2477				oprangeset(ALDPSW, t)
  2478				oprangeset(AFLDPS, t)
  2479	
  2480			case AERET:
  2481				oprangeset(AWFE, t)
  2482				oprangeset(AWFI, t)
  2483				oprangeset(AYIELD, t)
  2484				oprangeset(ASEV, t)
  2485				oprangeset(ASEVL, t)
  2486				oprangeset(ADRPS, t)
  2487	
  2488			case ACBZ:
  2489				oprangeset(ACBZW, t)
  2490				oprangeset(ACBNZ, t)
  2491				oprangeset(ACBNZW, t)
  2492	
  2493			case ATBZ:
  2494				oprangeset(ATBNZ, t)
  2495	
  2496			case AADR, AADRP:
  2497				break
  2498	
  2499			case ACLREX:
  2500				break
  2501	
  2502			case ASVC:
  2503				oprangeset(AHVC, t)
  2504				oprangeset(AHLT, t)
  2505				oprangeset(ASMC, t)
  2506				oprangeset(ABRK, t)
  2507				oprangeset(ADCPS1, t)
  2508				oprangeset(ADCPS2, t)
  2509				oprangeset(ADCPS3, t)
  2510	
  2511			case AFADDS:
  2512				oprangeset(AFADDD, t)
  2513				oprangeset(AFSUBS, t)
  2514				oprangeset(AFSUBD, t)
  2515				oprangeset(AFMULS, t)
  2516				oprangeset(AFMULD, t)
  2517				oprangeset(AFNMULS, t)
  2518				oprangeset(AFNMULD, t)
  2519				oprangeset(AFDIVS, t)
  2520				oprangeset(AFMAXD, t)
  2521				oprangeset(AFMAXS, t)
  2522				oprangeset(AFMIND, t)
  2523				oprangeset(AFMINS, t)
  2524				oprangeset(AFMAXNMD, t)
  2525				oprangeset(AFMAXNMS, t)
  2526				oprangeset(AFMINNMD, t)
  2527				oprangeset(AFMINNMS, t)
  2528				oprangeset(AFDIVD, t)
  2529	
  2530			case AFMSUBD:
  2531				oprangeset(AFMSUBS, t)
  2532				oprangeset(AFMADDS, t)
  2533				oprangeset(AFMADDD, t)
  2534				oprangeset(AFNMSUBS, t)
  2535				oprangeset(AFNMSUBD, t)
  2536				oprangeset(AFNMADDS, t)
  2537				oprangeset(AFNMADDD, t)
  2538	
  2539			case AFCVTSD:
  2540				oprangeset(AFCVTDS, t)
  2541				oprangeset(AFABSD, t)
  2542				oprangeset(AFABSS, t)
  2543				oprangeset(AFNEGD, t)
  2544				oprangeset(AFNEGS, t)
  2545				oprangeset(AFSQRTD, t)
  2546				oprangeset(AFSQRTS, t)
  2547				oprangeset(AFRINTNS, t)
  2548				oprangeset(AFRINTND, t)
  2549				oprangeset(AFRINTPS, t)
  2550				oprangeset(AFRINTPD, t)
  2551				oprangeset(AFRINTMS, t)
  2552				oprangeset(AFRINTMD, t)
  2553				oprangeset(AFRINTZS, t)
  2554				oprangeset(AFRINTZD, t)
  2555				oprangeset(AFRINTAS, t)
  2556				oprangeset(AFRINTAD, t)
  2557				oprangeset(AFRINTXS, t)
  2558				oprangeset(AFRINTXD, t)
  2559				oprangeset(AFRINTIS, t)
  2560				oprangeset(AFRINTID, t)
  2561				oprangeset(AFCVTDH, t)
  2562				oprangeset(AFCVTHS, t)
  2563				oprangeset(AFCVTHD, t)
  2564				oprangeset(AFCVTSH, t)
  2565	
  2566			case AFCMPS:
  2567				oprangeset(AFCMPD, t)
  2568				oprangeset(AFCMPES, t)
  2569				oprangeset(AFCMPED, t)
  2570	
  2571			case AFCCMPS:
  2572				oprangeset(AFCCMPD, t)
  2573				oprangeset(AFCCMPES, t)
  2574				oprangeset(AFCCMPED, t)
  2575	
  2576			case AFCSELD:
  2577				oprangeset(AFCSELS, t)
  2578	
  2579			case AFMOVS, AFMOVD:
  2580				break
  2581	
  2582			case AFCVTZSD:
  2583				oprangeset(AFCVTZSDW, t)
  2584				oprangeset(AFCVTZSS, t)
  2585				oprangeset(AFCVTZSSW, t)
  2586				oprangeset(AFCVTZUD, t)
  2587				oprangeset(AFCVTZUDW, t)
  2588				oprangeset(AFCVTZUS, t)
  2589				oprangeset(AFCVTZUSW, t)
  2590	
  2591			case ASCVTFD:
  2592				oprangeset(ASCVTFS, t)
  2593				oprangeset(ASCVTFWD, t)
  2594				oprangeset(ASCVTFWS, t)
  2595				oprangeset(AUCVTFD, t)
  2596				oprangeset(AUCVTFS, t)
  2597				oprangeset(AUCVTFWD, t)
  2598				oprangeset(AUCVTFWS, t)
  2599	
  2600			case ASYS:
  2601				oprangeset(AAT, t)
  2602				oprangeset(ADC, t)
  2603				oprangeset(AIC, t)
  2604				oprangeset(ATLBI, t)
  2605	
  2606			case ASYSL, AHINT:
  2607				break
  2608	
  2609			case ADMB:
  2610				oprangeset(ADSB, t)
  2611				oprangeset(AISB, t)
  2612	
  2613			case AMRS, AMSR:
  2614				break
  2615	
  2616			case ALDAR:
  2617				oprangeset(ALDARW, t)
  2618				oprangeset(ALDARB, t)
  2619				oprangeset(ALDARH, t)
  2620				fallthrough
  2621	
  2622			case ALDXR:
  2623				oprangeset(ALDXRB, t)
  2624				oprangeset(ALDXRH, t)
  2625				oprangeset(ALDXRW, t)
  2626	
  2627			case ALDAXR:
  2628				oprangeset(ALDAXRB, t)
  2629				oprangeset(ALDAXRH, t)
  2630				oprangeset(ALDAXRW, t)
  2631	
  2632			case ALDXP:
  2633				oprangeset(ALDXPW, t)
  2634				oprangeset(ALDAXP, t)
  2635				oprangeset(ALDAXPW, t)
  2636	
  2637			case ASTLR:
  2638				oprangeset(ASTLRB, t)
  2639				oprangeset(ASTLRH, t)
  2640				oprangeset(ASTLRW, t)
  2641	
  2642			case ASTXR:
  2643				oprangeset(ASTXRB, t)
  2644				oprangeset(ASTXRH, t)
  2645				oprangeset(ASTXRW, t)
  2646	
  2647			case ASTLXR:
  2648				oprangeset(ASTLXRB, t)
  2649				oprangeset(ASTLXRH, t)
  2650				oprangeset(ASTLXRW, t)
  2651	
  2652			case ASTXP:
  2653				oprangeset(ASTLXP, t)
  2654				oprangeset(ASTLXPW, t)
  2655				oprangeset(ASTXPW, t)
  2656	
  2657			case AVADDP:
  2658				oprangeset(AVAND, t)
  2659				oprangeset(AVCMEQ, t)
  2660				oprangeset(AVORR, t)
  2661				oprangeset(AVEOR, t)
  2662	
  2663			case AVADD:
  2664				oprangeset(AVSUB, t)
  2665	
  2666			case AAESD:
  2667				oprangeset(AAESE, t)
  2668				oprangeset(AAESMC, t)
  2669				oprangeset(AAESIMC, t)
  2670				oprangeset(ASHA1SU1, t)
  2671				oprangeset(ASHA256SU0, t)
  2672	
  2673			case ASHA1C:
  2674				oprangeset(ASHA1P, t)
  2675				oprangeset(ASHA1M, t)
  2676	
  2677			case ASHA256H:
  2678				oprangeset(ASHA256H2, t)
  2679	
  2680			case ASHA1SU0:
  2681				oprangeset(ASHA256SU1, t)
  2682	
  2683			case AVADDV:
  2684				oprangeset(AVUADDLV, t)
  2685	
  2686			case AVFMLA:
  2687				oprangeset(AVFMLS, t)
  2688	
  2689			case AVPMULL:
  2690				oprangeset(AVPMULL2, t)
  2691	
  2692			case AVUSHR:
  2693				oprangeset(AVSHL, t)
  2694				oprangeset(AVSRI, t)
  2695	
  2696			case AVREV32:
  2697				oprangeset(AVRBIT, t)
  2698				oprangeset(AVREV64, t)
  2699	
  2700			case AVZIP1:
  2701				oprangeset(AVZIP2, t)
  2702	
  2703			case ASHA1H,
  2704				AVCNT,
  2705				AVMOV,
  2706				AVLD1,
  2707				AVST1,
  2708				AVTBL,
  2709				AVDUP,
  2710				AVMOVI,
  2711				APRFM,
  2712				AVEXT:
  2713				break
  2714	
  2715			case obj.ANOP,
  2716				obj.AUNDEF,
  2717				obj.AFUNCDATA,
  2718				obj.APCDATA,
  2719				obj.ADUFFZERO,
  2720				obj.ADUFFCOPY:
  2721				break
  2722			}
  2723		}
  2724	}
  2725	
  2726	// chipfloat7() checks if the immediate constants available in  FMOVS/FMOVD instructions.
  2727	// For details of the range of constants available, see
  2728	// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
  2729	func (c *ctxt7) chipfloat7(e float64) int {
  2730		ei := math.Float64bits(e)
  2731		l := uint32(int32(ei))
  2732		h := uint32(int32(ei >> 32))
  2733	
  2734		if l != 0 || h&0xffff != 0 {
  2735			return -1
  2736		}
  2737		h1 := h & 0x7fc00000
  2738		if h1 != 0x40000000 && h1 != 0x3fc00000 {
  2739			return -1
  2740		}
  2741		n := 0
  2742	
  2743		// sign bit (a)
  2744		if h&0x80000000 != 0 {
  2745			n |= 1 << 7
  2746		}
  2747	
  2748		// exp sign bit (b)
  2749		if h1 == 0x3fc00000 {
  2750			n |= 1 << 6
  2751		}
  2752	
  2753		// rest of exp and mantissa (cd-efgh)
  2754		n |= int((h >> 16) & 0x3f)
  2755	
  2756		//print("match %.8lux %.8lux %d\n", l, h, n);
  2757		return n
  2758	}
  2759	
  2760	/* form offset parameter to SYS; special register number */
  2761	func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
  2762		return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
  2763	}
  2764	
  2765	func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
  2766		return SYSARG5(0, op1, Cn, Cm, op2)
  2767	}
  2768	
  2769	// checkUnpredictable checks if the sourse and transfer registers are the same register.
  2770	// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
  2771	func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
  2772		if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
  2773			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  2774		}
  2775		if isload && rt1 == rt2 {
  2776			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  2777		}
  2778	}
  2779	
  2780	/* checkindex checks if index >= 0 && index <= maxindex */
  2781	func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
  2782		if index < 0 || index > maxindex {
  2783			c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
  2784		}
  2785	}
  2786	
  2787	/* checkoffset checks whether the immediate offset is valid for VLD1.P and VST1.P */
  2788	func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
  2789		var offset, list, n int64
  2790		switch as {
  2791		case AVLD1:
  2792			offset = p.From.Offset
  2793			list = p.To.Offset
  2794		case AVST1:
  2795			offset = p.To.Offset
  2796			list = p.From.Offset
  2797		default:
  2798			c.ctxt.Diag("invalid operation on op %v", p.As)
  2799		}
  2800		opcode := (list >> 12) & 15
  2801		q := (list >> 30) & 1
  2802		if offset == 0 {
  2803			return
  2804		}
  2805		switch opcode {
  2806		case 0x7:
  2807			n = 1 // one register
  2808		case 0xa:
  2809			n = 2 // two registers
  2810		case 0x6:
  2811			n = 3 // three registers
  2812		case 0x2:
  2813			n = 4 // four registers
  2814		default:
  2815			c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  2816		}
  2817		if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
  2818			c.ctxt.Diag("invalid post-increment offset: %v", p)
  2819		}
  2820	}
  2821	
  2822	/* checkShiftAmount checks whether the index shift amount is valid */
  2823	/* for load with register offset instructions */
  2824	func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
  2825		var amount int16
  2826		amount = (a.Index >> 5) & 7
  2827		switch p.As {
  2828		case AMOVB, AMOVBU:
  2829			if amount != 0 {
  2830				c.ctxt.Diag("invalid index shift amount: %v", p)
  2831			}
  2832		case AMOVH, AMOVHU:
  2833			if amount != 1 && amount != 0 {
  2834				c.ctxt.Diag("invalid index shift amount: %v", p)
  2835			}
  2836		case AMOVW, AMOVWU, AFMOVS:
  2837			if amount != 2 && amount != 0 {
  2838				c.ctxt.Diag("invalid index shift amount: %v", p)
  2839			}
  2840		case AMOVD, AFMOVD:
  2841			if amount != 3 && amount != 0 {
  2842				c.ctxt.Diag("invalid index shift amount: %v", p)
  2843			}
  2844		default:
  2845			panic("invalid operation")
  2846		}
  2847	}
  2848	
  2849	func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
  2850		var os [5]uint32
  2851		o1 := uint32(0)
  2852		o2 := uint32(0)
  2853		o3 := uint32(0)
  2854		o4 := uint32(0)
  2855		o5 := uint32(0)
  2856		if false { /*debug['P']*/
  2857			fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  2858		}
  2859		switch o.type_ {
  2860		default:
  2861			c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  2862	
  2863		case 0: /* pseudo ops */
  2864			break
  2865	
  2866		case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
  2867			o1 = c.oprrr(p, p.As)
  2868	
  2869			rf := int(p.From.Reg)
  2870			rt := int(p.To.Reg)
  2871			r := int(p.Reg)
  2872			if p.To.Type == obj.TYPE_NONE {
  2873				rt = REGZERO
  2874			}
  2875			if r == 0 {
  2876				r = rt
  2877			}
  2878			o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  2879	
  2880		case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
  2881			o1 = c.opirr(p, p.As)
  2882	
  2883			rt := int(p.To.Reg)
  2884			if p.To.Type == obj.TYPE_NONE {
  2885				if (o1 & Sbit) == 0 {
  2886					c.ctxt.Diag("ineffective ZR destination\n%v", p)
  2887				}
  2888				rt = REGZERO
  2889			}
  2890	
  2891			r := int(p.Reg)
  2892			if r == 0 {
  2893				r = rt
  2894			}
  2895			v := int32(c.regoff(&p.From))
  2896			o1 = c.oaddi(p, int32(o1), v, r, rt)
  2897	
  2898		case 3: /* op R<<n[,R],R (shifted register) */
  2899			o1 = c.oprrr(p, p.As)
  2900	
  2901			amount := (p.From.Offset >> 10) & 63
  2902			is64bit := o1 & (1 << 31)
  2903			if is64bit == 0 && amount >= 32 {
  2904				c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
  2905			}
  2906			o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  2907			rt := int(p.To.Reg)
  2908			if p.To.Type == obj.TYPE_NONE {
  2909				rt = REGZERO
  2910			}
  2911			r := int(p.Reg)
  2912			if p.As == AMVN || p.As == AMVNW {
  2913				r = REGZERO
  2914			} else if r == 0 {
  2915				r = rt
  2916			}
  2917			o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  2918	
  2919		case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */
  2920			o1 = c.opirr(p, p.As)
  2921	
  2922			rt := int(p.To.Reg)
  2923			r := int(o.param)
  2924			if r == 0 {
  2925				r = REGZERO
  2926			} else if r == REGFROM {
  2927				r = int(p.From.Reg)
  2928			}
  2929			if r == 0 {
  2930				r = REGSP
  2931			}
  2932			v := int32(c.regoff(&p.From))
  2933			if (v & 0xFFF000) != 0 {
  2934				v >>= 12
  2935				o1 |= 1 << 22 /* shift, by 12 */
  2936			}
  2937	
  2938			o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  2939	
  2940		case 5: /* b s; bl s */
  2941			o1 = c.opbra(p, p.As)
  2942	
  2943			if p.To.Sym == nil {
  2944				o1 |= uint32(c.brdist(p, 0, 26, 2))
  2945				break
  2946			}
  2947	
  2948			rel := obj.Addrel(c.cursym)
  2949			rel.Off = int32(c.pc)
  2950			rel.Siz = 4
  2951			rel.Sym = p.To.Sym
  2952			rel.Add = p.To.Offset
  2953			rel.Type = objabi.R_CALLARM64
  2954	
  2955		case 6: /* b ,O(R); bl ,O(R) */
  2956			o1 = c.opbrr(p, p.As)
  2957	
  2958			o1 |= uint32(p.To.Reg&31) << 5
  2959			rel := obj.Addrel(c.cursym)
  2960			rel.Off = int32(c.pc)
  2961			rel.Siz = 0
  2962			rel.Type = objabi.R_CALLIND
  2963	
  2964		case 7: /* beq s */
  2965			o1 = c.opbra(p, p.As)
  2966	
  2967			o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  2968	
  2969		case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
  2970			rt := int(p.To.Reg)
  2971	
  2972			rf := int(p.Reg)
  2973			if rf == 0 {
  2974				rf = rt
  2975			}
  2976			v := int32(p.From.Offset)
  2977			switch p.As {
  2978			case AASR:
  2979				o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
  2980	
  2981			case AASRW:
  2982				o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
  2983	
  2984			case ALSL:
  2985				o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
  2986	
  2987			case ALSLW:
  2988				o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
  2989	
  2990			case ALSR:
  2991				o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
  2992	
  2993			case ALSRW:
  2994				o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
  2995	
  2996			case AROR:
  2997				o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
  2998	
  2999			case ARORW:
  3000				o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
  3001	
  3002			default:
  3003				c.ctxt.Diag("bad shift $con\n%v", p)
  3004				break
  3005			}
  3006	
  3007		case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
  3008			o1 = c.oprrr(p, p.As)
  3009	
  3010			r := int(p.Reg)
  3011			if r == 0 {
  3012				r = int(p.To.Reg)
  3013			}
  3014			o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
  3015	
  3016		case 10: /* brk/hvc/.../svc [$con] */
  3017			o1 = c.opimm(p, p.As)
  3018	
  3019			if p.From.Type != obj.TYPE_NONE {
  3020				o1 |= uint32((p.From.Offset & 0xffff) << 5)
  3021			}
  3022	
  3023		case 11: /* dword */
  3024			c.aclass(&p.To)
  3025	
  3026			o1 = uint32(c.instoffset)
  3027			o2 = uint32(c.instoffset >> 32)
  3028			if p.To.Sym != nil {
  3029				rel := obj.Addrel(c.cursym)
  3030				rel.Off = int32(c.pc)
  3031				rel.Siz = 8
  3032				rel.Sym = p.To.Sym
  3033				rel.Add = p.To.Offset
  3034				rel.Type = objabi.R_ADDR
  3035				o2 = 0
  3036				o1 = o2
  3037			}
  3038	
  3039		case 12: /* movT $vcon, reg */
  3040			num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
  3041			if num == 0 {
  3042				c.ctxt.Diag("invalid constant: %v", p)
  3043			}
  3044			o1 = os[0]
  3045			o2 = os[1]
  3046			o3 = os[2]
  3047			o4 = os[3]
  3048	
  3049		case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
  3050			o := uint32(0)
  3051			num := uint8(0)
  3052			cls := oclass(&p.From)
  3053			if isADDWop(p.As) {
  3054				if !cmp(C_LCON, cls) {
  3055					c.ctxt.Diag("illegal combination: %v", p)
  3056				}
  3057				num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3058			} else {
  3059				num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3060			}
  3061			if num == 0 {
  3062				c.ctxt.Diag("invalid constant: %v", p)
  3063			}
  3064			rt := int(p.To.Reg)
  3065			if p.To.Type == obj.TYPE_NONE {
  3066				rt = REGZERO
  3067			}
  3068			r := int(p.Reg)
  3069			if r == 0 {
  3070				r = rt
  3071			}
  3072			if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
  3073				o = c.opxrrr(p, p.As, false)
  3074				o |= REGTMP & 31 << 16
  3075				o |= LSL0_64
  3076			} else {
  3077				o = c.oprrr(p, p.As)
  3078				o |= REGTMP & 31 << 16 /* shift is 0 */
  3079			}
  3080	
  3081			o |= uint32(r&31) << 5
  3082			o |= uint32(rt & 31)
  3083	
  3084			os[num] = o
  3085			o1 = os[0]
  3086			o2 = os[1]
  3087			o3 = os[2]
  3088			o4 = os[3]
  3089			o5 = os[4]
  3090	
  3091		case 14: /* word */
  3092			if c.aclass(&p.To) == C_ADDR {
  3093				c.ctxt.Diag("address constant needs DWORD\n%v", p)
  3094			}
  3095			o1 = uint32(c.instoffset)
  3096			if p.To.Sym != nil {
  3097				// This case happens with words generated
  3098				// in the PC stream as part of the literal pool.
  3099				rel := obj.Addrel(c.cursym)
  3100	
  3101				rel.Off = int32(c.pc)
  3102				rel.Siz = 4
  3103				rel.Sym = p.To.Sym
  3104				rel.Add = p.To.Offset
  3105				rel.Type = objabi.R_ADDR
  3106				o1 = 0
  3107			}
  3108	
  3109		case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
  3110			o1 = c.oprrr(p, p.As)
  3111	
  3112			rf := int(p.From.Reg)
  3113			rt := int(p.To.Reg)
  3114			var r int
  3115			var ra int
  3116			if p.From3Type() == obj.TYPE_REG {
  3117				r = int(p.GetFrom3().Reg)
  3118				ra = int(p.Reg)
  3119				if ra == 0 {
  3120					ra = REGZERO
  3121				}
  3122			} else {
  3123				r = int(p.Reg)
  3124				if r == 0 {
  3125					r = rt
  3126				}
  3127				ra = REGZERO
  3128			}
  3129	
  3130			o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  3131	
  3132		case 16: /* XremY R[,R],R -> XdivY; XmsubY */
  3133			o1 = c.oprrr(p, p.As)
  3134	
  3135			rf := int(p.From.Reg)
  3136			rt := int(p.To.Reg)
  3137			r := int(p.Reg)
  3138			if r == 0 {
  3139				r = rt
  3140			}
  3141			o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
  3142			o2 = c.oprrr(p, AMSUBW)
  3143			o2 |= o1 & (1 << 31) /* same size */
  3144			o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
  3145	
  3146		case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
  3147			o1 = c.oprrr(p, p.As)
  3148	
  3149			rf := int(p.From.Reg)
  3150			rt := int(p.To.Reg)
  3151			r := int(p.Reg)
  3152			if p.To.Type == obj.TYPE_NONE {
  3153				rt = REGZERO
  3154			}
  3155			if r == 0 {
  3156				r = REGZERO
  3157			}
  3158			o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3159	
  3160		case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
  3161			o1 = c.oprrr(p, p.As)
  3162	
  3163			cond := int(p.From.Reg)
  3164			if cond < COND_EQ || cond > COND_NV {
  3165				c.ctxt.Diag("invalid condition: %v", p)
  3166			} else {
  3167				cond -= COND_EQ
  3168			}
  3169	
  3170			r := int(p.Reg)
  3171			var rf int
  3172			if r != 0 {
  3173				if p.From3Type() == obj.TYPE_NONE {
  3174					/* CINC/CINV/CNEG */
  3175					rf = r
  3176					cond ^= 1
  3177				} else {
  3178					rf = int(p.GetFrom3().Reg) /* CSEL */
  3179				}
  3180			} else {
  3181				/* CSET */
  3182				rf = REGZERO
  3183				r = rf
  3184				cond ^= 1
  3185			}
  3186	
  3187			rt := int(p.To.Reg)
  3188			o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
  3189	
  3190		case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
  3191			nzcv := int(p.To.Offset)
  3192	
  3193			cond := int(p.From.Reg)
  3194			if cond < COND_EQ || cond > COND_NV {
  3195				c.ctxt.Diag("invalid condition\n%v", p)
  3196			} else {
  3197				cond -= COND_EQ
  3198			}
  3199			var rf int
  3200			if p.GetFrom3().Type == obj.TYPE_REG {
  3201				o1 = c.oprrr(p, p.As)
  3202				rf = int(p.GetFrom3().Reg) /* Rm */
  3203			} else {
  3204				o1 = c.opirr(p, p.As)
  3205				rf = int(p.GetFrom3().Offset & 0x1F)
  3206			}
  3207	
  3208			o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
  3209	
  3210		case 20: /* movT R,O(R) -> strT */
  3211			v := int32(c.regoff(&p.To))
  3212			sz := int32(1 << uint(movesize(p.As)))
  3213	
  3214			r := int(p.To.Reg)
  3215			if r == 0 {
  3216				r = int(o.param)
  3217			}
  3218			if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3219				o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
  3220			} else {
  3221				v = int32(c.offsetshift(p, int64(v), int(o.a4)))
  3222				o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
  3223			}
  3224	
  3225		case 21: /* movT O(R),R -> ldrT */
  3226			v := int32(c.regoff(&p.From))
  3227			sz := int32(1 << uint(movesize(p.As)))
  3228	
  3229			r := int(p.From.Reg)
  3230			if r == 0 {
  3231				r = int(o.param)
  3232			}
  3233			if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3234				o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
  3235			} else {
  3236				v = int32(c.offsetshift(p, int64(v), int(o.a1)))
  3237				//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
  3238				o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
  3239			}
  3240	
  3241		case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
  3242			if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
  3243				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3244			}
  3245	
  3246			v := int32(p.From.Offset)
  3247	
  3248			if v < -256 || v > 255 {
  3249				c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  3250			}
  3251			o1 = c.opldrpp(p, p.As)
  3252			if o.scond == C_XPOST {
  3253				o1 |= 1 << 10
  3254			} else {
  3255				o1 |= 3 << 10
  3256			}
  3257			o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
  3258	
  3259		case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
  3260			if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
  3261				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3262			}
  3263	
  3264			v := int32(p.To.Offset)
  3265	
  3266			if v < -256 || v > 255 {
  3267				c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  3268			}
  3269			o1 = LD2STR(c.opldrpp(p, p.As))
  3270			if o.scond == C_XPOST {
  3271				o1 |= 1 << 10
  3272			} else {
  3273				o1 |= 3 << 10
  3274			}
  3275			o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
  3276	
  3277		case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
  3278			rf := int(p.From.Reg)
  3279			rt := int(p.To.Reg)
  3280			s := rf == REGSP || rt == REGSP
  3281			if p.As == AMVN || p.As == AMVNW {
  3282				if s {
  3283					c.ctxt.Diag("illegal SP reference\n%v", p)
  3284				}
  3285				o1 = c.oprrr(p, p.As)
  3286				o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3287			} else if s {
  3288				o1 = c.opirr(p, p.As)
  3289				o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3290			} else {
  3291				o1 = c.oprrr(p, p.As)
  3292				o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3293			}
  3294	
  3295		case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
  3296			o1 = c.oprrr(p, p.As)
  3297	
  3298			rf := int(p.From.Reg)
  3299			if rf == C_NONE {
  3300				rf = int(p.To.Reg)
  3301			}
  3302			rt := int(p.To.Reg)
  3303			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3304	
  3305		case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
  3306			o1 = c.oprrr(p, p.As)
  3307	
  3308			o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  3309			rt := int(p.To.Reg)
  3310			o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
  3311	
  3312		case 27: /* op Rm<<n[,Rn],Rd (extended register) */
  3313			if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
  3314				amount := (p.From.Reg >> 5) & 7
  3315				if amount > 4 {
  3316					c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
  3317				}
  3318				o1 = c.opxrrr(p, p.As, true)
  3319				o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
  3320			} else {
  3321				o1 = c.opxrrr(p, p.As, false)
  3322				o1 |= uint32(p.From.Reg&31) << 16
  3323			}
  3324			rt := int(p.To.Reg)
  3325			if p.To.Type == obj.TYPE_NONE {
  3326				rt = REGZERO
  3327			}
  3328			r := int(p.Reg)
  3329			if r == 0 {
  3330				r = rt
  3331			}
  3332			o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  3333	
  3334		case 28: /* logop $vcon, [R], R (64 bit literal) */
  3335			o := uint32(0)
  3336			num := uint8(0)
  3337			cls := oclass(&p.From)
  3338			if isANDWop(p.As) {
  3339				if !cmp(C_LCON, cls) {
  3340					c.ctxt.Diag("illegal combination: %v", p)
  3341				}
  3342				num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3343			} else {
  3344				num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3345			}
  3346	
  3347			if num == 0 {
  3348				c.ctxt.Diag("invalid constant: %v", p)
  3349			}
  3350			rt := int(p.To.Reg)
  3351			if p.To.Type == obj.TYPE_NONE {
  3352				rt = REGZERO
  3353			}
  3354			r := int(p.Reg)
  3355			if r == 0 {
  3356				r = rt
  3357			}
  3358			o = c.oprrr(p, p.As)
  3359			o |= REGTMP & 31 << 16 /* shift is 0 */
  3360			o |= uint32(r&31) << 5
  3361			o |= uint32(rt & 31)
  3362	
  3363			os[num] = o
  3364			o1 = os[0]
  3365			o2 = os[1]
  3366			o3 = os[2]
  3367			o4 = os[3]
  3368			o5 = os[4]
  3369	
  3370		case 29: /* op Rn, Rd */
  3371			fc := c.aclass(&p.From)
  3372			tc := c.aclass(&p.To)
  3373			if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
  3374				// FMOV Rx, Fy or FMOV Fy, Rx
  3375				o1 = FPCVTI(0, 0, 0, 0, 6)
  3376				if p.As == AFMOVD {
  3377					o1 |= 1<<31 | 1<<22 // 64-bit
  3378				}
  3379				if fc == C_REG || fc == C_ZCON {
  3380					o1 |= 1 << 16 // FMOV Rx, Fy
  3381				}
  3382			} else {
  3383				o1 = c.oprrr(p, p.As)
  3384			}
  3385			o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
  3386	
  3387		case 30: /* movT R,L(R) -> strT */
  3388			// if offset L can be split into hi+lo, and both fit into instructions, do
  3389			//	add $hi, R, Rtmp
  3390			//	str R, lo(Rtmp)
  3391			// otherwise, use constant pool
  3392			//	mov $L, Rtmp (from constant pool)
  3393			//	str R, (R+Rtmp)
  3394			s := movesize(o.as)
  3395			if s < 0 {
  3396				c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3397			}
  3398	
  3399			r := int(p.To.Reg)
  3400			if r == 0 {
  3401				r = int(o.param)
  3402			}
  3403	
  3404			v := int32(c.regoff(&p.To))
  3405			var hi int32
  3406			if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3407				// negative or unaligned offset, use constant pool
  3408				goto storeusepool
  3409			}
  3410	
  3411			hi = v - (v & (0xFFF << uint(s)))
  3412			if hi&0xFFF != 0 {
  3413				c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3414			}
  3415			if hi&^0xFFF000 != 0 {
  3416				// hi doesn't fit into an ADD instruction
  3417				goto storeusepool
  3418			}
  3419	
  3420			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3421			o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
  3422			break
  3423	
  3424		storeusepool:
  3425			if r == REGTMP || p.From.Reg == REGTMP {
  3426				c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  3427			}
  3428			o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  3429			o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
  3430	
  3431		case 31: /* movT L(R), R -> ldrT */
  3432			// if offset L can be split into hi+lo, and both fit into instructions, do
  3433			//	add $hi, R, Rtmp
  3434			//	ldr lo(Rtmp), R
  3435			// otherwise, use constant pool
  3436			//	mov $L, Rtmp (from constant pool)
  3437			//	ldr (R+Rtmp), R
  3438			s := movesize(o.as)
  3439			if s < 0 {
  3440				c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3441			}
  3442	
  3443			r := int(p.From.Reg)
  3444			if r == 0 {
  3445				r = int(o.param)
  3446			}
  3447	
  3448			v := int32(c.regoff(&p.From))
  3449			var hi int32
  3450			if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3451				// negative or unaligned offset, use constant pool
  3452				goto loadusepool
  3453			}
  3454	
  3455			hi = v - (v & (0xFFF << uint(s)))
  3456			if (hi & 0xFFF) != 0 {
  3457				c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3458			}
  3459			if hi&^0xFFF000 != 0 {
  3460				// hi doesn't fit into an ADD instruction
  3461				goto loadusepool
  3462			}
  3463	
  3464			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3465			o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
  3466			break
  3467	
  3468		loadusepool:
  3469			if r == REGTMP || p.From.Reg == REGTMP {
  3470				c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  3471			}
  3472			o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3473			o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
  3474	
  3475		case 32: /* mov $con, R -> movz/movn */
  3476			o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
  3477	
  3478		case 33: /* movk $uimm16 << pos */
  3479			o1 = c.opirr(p, p.As)
  3480	
  3481			d := p.From.Offset
  3482			s := movcon(d)
  3483			if s < 0 || s >= 4 {
  3484				c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
  3485			}
  3486			if (o1&S64) == 0 && s >= 2 {
  3487				c.ctxt.Diag("illegal bit position\n%v", p)
  3488			}
  3489			if ((d >> uint(s*16)) >> 16) != 0 {
  3490				c.ctxt.Diag("requires uimm16\n%v", p)
  3491			}
  3492			rt := int(p.To.Reg)
  3493	
  3494			o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
  3495	
  3496		case 34: /* mov $lacon,R */
  3497			o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3498	
  3499			if o1 == 0 {
  3500				break
  3501			}
  3502			o2 = c.opxrrr(p, AADD, false)
  3503			o2 |= REGTMP & 31 << 16
  3504			o2 |= LSL0_64
  3505			r := int(p.From.Reg)
  3506			if r == 0 {
  3507				r = int(o.param)
  3508			}
  3509			o2 |= uint32(r&31) << 5
  3510			o2 |= uint32(p.To.Reg & 31)
  3511	
  3512		case 35: /* mov SPR,R -> mrs */
  3513			o1 = c.oprrr(p, AMRS)
  3514	
  3515			v := uint32(0)
  3516			for i := 0; i < len(systemreg); i++ {
  3517				if systemreg[i].reg == p.From.Reg {
  3518					v = systemreg[i].enc
  3519					break
  3520				}
  3521			}
  3522			if v == 0 {
  3523				c.ctxt.Diag("illegal system register:\n%v", p)
  3524			}
  3525			if (o1 & (v &^ (3 << 19))) != 0 {
  3526				c.ctxt.Diag("MRS register value overlap\n%v", p)
  3527			}
  3528	
  3529			o1 |= v
  3530			o1 |= uint32(p.To.Reg & 31)
  3531	
  3532		case 36: /* mov R,SPR */
  3533			o1 = c.oprrr(p, AMSR)
  3534	
  3535			v := uint32(0)
  3536			for i := 0; i < len(systemreg); i++ {
  3537				if systemreg[i].reg == p.To.Reg {
  3538					v = systemreg[i].enc
  3539					break
  3540				}
  3541			}
  3542			if v == 0 {
  3543				c.ctxt.Diag("illegal system register:\n%v", p)
  3544			}
  3545			if (o1 & (v &^ (3 << 19))) != 0 {
  3546				c.ctxt.Diag("MSR register value overlap\n%v", p)
  3547			}
  3548	
  3549			o1 |= v
  3550			o1 |= uint32(p.From.Reg & 31)
  3551	
  3552		case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
  3553			if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
  3554				c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
  3555			}
  3556			o1 = c.opirr(p, AMSR)
  3557			o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
  3558			v := uint32(0)
  3559			for i := 0; i < len(pstatefield); i++ {
  3560				if pstatefield[i].reg == p.To.Reg {
  3561					v = pstatefield[i].enc
  3562					break
  3563				}
  3564			}
  3565	
  3566			if v == 0 {
  3567				c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
  3568			}
  3569			o1 |= v
  3570	
  3571		case 38: /* clrex [$imm] */
  3572			o1 = c.opimm(p, p.As)
  3573	
  3574			if p.To.Type == obj.TYPE_NONE {
  3575				o1 |= 0xF << 8
  3576			} else {
  3577				o1 |= uint32((p.To.Offset & 0xF) << 8)
  3578			}
  3579	
  3580		case 39: /* cbz R, rel */
  3581			o1 = c.opirr(p, p.As)
  3582	
  3583			o1 |= uint32(p.From.Reg & 31)
  3584			o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  3585	
  3586		case 40: /* tbz */
  3587			o1 = c.opirr(p, p.As)
  3588	
  3589			v := int32(p.From.Offset)
  3590			if v < 0 || v > 63 {
  3591				c.ctxt.Diag("illegal bit number\n%v", p)
  3592			}
  3593			o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
  3594			o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
  3595			o1 |= uint32(p.Reg & 31)
  3596	
  3597		case 41: /* eret, nop, others with no operands */
  3598			o1 = c.op0(p, p.As)
  3599	
  3600		case 42: /* bfm R,r,s,R */
  3601			o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
  3602	
  3603		case 43: /* bfm aliases */
  3604			r := int(p.From.Offset)
  3605			s := int(p.GetFrom3().Offset)
  3606			rf := int(p.Reg)
  3607			rt := int(p.To.Reg)
  3608			if rf == 0 {
  3609				rf = rt
  3610			}
  3611			switch p.As {
  3612			case ABFI:
  3613				if r != 0 {
  3614					r = 64 - r
  3615				}
  3616				o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
  3617	
  3618			case ABFIW:
  3619				if r != 0 {
  3620					r = 32 - r
  3621				}
  3622				o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
  3623	
  3624			case ABFXIL:
  3625				o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
  3626	
  3627			case ABFXILW:
  3628				o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
  3629	
  3630			case ASBFIZ:
  3631				if r != 0 {
  3632					r = 64 - r
  3633				}
  3634				o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
  3635	
  3636			case ASBFIZW:
  3637				if r != 0 {
  3638					r = 32 - r
  3639				}
  3640				o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
  3641	
  3642			case ASBFX:
  3643				o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
  3644	
  3645			case ASBFXW:
  3646				o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
  3647	
  3648			case AUBFIZ:
  3649				if r != 0 {
  3650					r = 64 - r
  3651				}
  3652				o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
  3653	
  3654			case AUBFIZW:
  3655				if r != 0 {
  3656					r = 32 - r
  3657				}
  3658				o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
  3659	
  3660			case AUBFX:
  3661				o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
  3662	
  3663			case AUBFXW:
  3664				o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
  3665	
  3666			default:
  3667				c.ctxt.Diag("bad bfm alias\n%v", p)
  3668				break
  3669			}
  3670	
  3671		case 44: /* extr $b, Rn, Rm, Rd */
  3672			o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
  3673	
  3674		case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
  3675			rf := int(p.From.Reg)
  3676	
  3677			rt := int(p.To.Reg)
  3678			as := p.As
  3679			if rf == REGZERO {
  3680				as = AMOVWU /* clearer in disassembly */
  3681			}
  3682			switch as {
  3683			case AMOVB, ASXTB:
  3684				o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
  3685	
  3686			case AMOVH, ASXTH:
  3687				o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
  3688	
  3689			case AMOVW, ASXTW:
  3690				o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
  3691	
  3692			case AMOVBU, AUXTB:
  3693				o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
  3694	
  3695			case AMOVHU, AUXTH:
  3696				o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
  3697	
  3698			case AMOVWU:
  3699				o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3700	
  3701			case AUXTW:
  3702				o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
  3703	
  3704			case ASXTBW:
  3705				o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
  3706	
  3707			case ASXTHW:
  3708				o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
  3709	
  3710			case AUXTBW:
  3711				o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
  3712	
  3713			case AUXTHW:
  3714				o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
  3715	
  3716			default:
  3717				c.ctxt.Diag("bad sxt %v", as)
  3718				break
  3719			}
  3720	
  3721		case 46: /* cls */
  3722			o1 = c.opbit(p, p.As)
  3723	
  3724			o1 |= uint32(p.From.Reg&31) << 5
  3725			o1 |= uint32(p.To.Reg & 31)
  3726	
  3727		case 47: /* SWPx/LDADDx/LDANDx/LDEORx/LDORx Rs, (Rb), Rt */
  3728			rs := p.From.Reg
  3729			rt := p.RegTo2
  3730			rb := p.To.Reg
  3731	
  3732			fields := atomicInstructions[p.As]
  3733			// rt can't be sp. rt can't be r31 when field A is 0, A bit is the 23rd bit.
  3734			if rt == REG_RSP || (rt == REGZERO && (fields&(1<<23) == 0)) {
  3735				c.ctxt.Diag("illegal destination register: %v\n", p)
  3736			}
  3737			o1 |= fields | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  3738	
  3739		case 48: /* ADD $C_ADDCON2, Rm, Rd */
  3740			op := c.opirr(p, p.As)
  3741			if op&Sbit != 0 {
  3742				c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
  3743			}
  3744			rt := int(p.To.Reg)
  3745			r := int(p.Reg)
  3746			if r == 0 {
  3747				r = rt
  3748			}
  3749			o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
  3750			o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
  3751	
  3752		case 50: /* sys/sysl */
  3753			o1 = c.opirr(p, p.As)
  3754	
  3755			if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
  3756				c.ctxt.Diag("illegal SYS argument\n%v", p)
  3757			}
  3758			o1 |= uint32(p.From.Offset)
  3759			if p.To.Type == obj.TYPE_REG {
  3760				o1 |= uint32(p.To.Reg & 31)
  3761			} else if p.Reg != 0 {
  3762				o1 |= uint32(p.Reg & 31)
  3763			} else {
  3764				o1 |= 0x1F
  3765			}
  3766	
  3767		case 51: /* dmb */
  3768			o1 = c.opirr(p, p.As)
  3769	
  3770			if p.From.Type == obj.TYPE_CONST {
  3771				o1 |= uint32((p.From.Offset & 0xF) << 8)
  3772			}
  3773	
  3774		case 52: /* hint */
  3775			o1 = c.opirr(p, p.As)
  3776	
  3777			o1 |= uint32((p.From.Offset & 0x7F) << 5)
  3778	
  3779		case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
  3780			a := p.As
  3781			rt := int(p.To.Reg)
  3782			if p.To.Type == obj.TYPE_NONE {
  3783				rt = REGZERO
  3784			}
  3785			r := int(p.Reg)
  3786			if r == 0 {
  3787				r = rt
  3788			}
  3789			mode := 64
  3790			v := uint64(p.From.Offset)
  3791			switch p.As {
  3792			case AANDW, AORRW, AEORW, AANDSW, ATSTW:
  3793				mode = 32
  3794			case ABIC, AORN, AEON, ABICS:
  3795				v = ^v
  3796			case ABICW, AORNW, AEONW, ABICSW:
  3797				v = ^v
  3798				mode = 32
  3799			}
  3800			o1 = c.opirr(p, a)
  3801			o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
  3802	
  3803		case 54: /* floating point arith */
  3804			o1 = c.oprrr(p, p.As)
  3805			rf := int(p.From.Reg)
  3806			rt := int(p.To.Reg)
  3807			r := int(p.Reg)
  3808			if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
  3809				r = rf
  3810				rf = 0
  3811			} else if r == 0 {
  3812				r = rt
  3813			}
  3814			o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3815	
  3816		case 55: /* floating-point constant */
  3817			var rf int
  3818			o1 = 0xf<<25 | 1<<21 | 1<<12
  3819			rf = c.chipfloat7(p.From.Val.(float64))
  3820			if rf < 0 {
  3821				c.ctxt.Diag("invalid floating-point immediate\n%v", p)
  3822			}
  3823			if p.As == AFMOVD {
  3824				o1 |= 1 << 22
  3825			}
  3826			o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
  3827	
  3828		case 56: /* floating point compare */
  3829			o1 = c.oprrr(p, p.As)
  3830	
  3831			var rf int
  3832			if p.From.Type == obj.TYPE_FCONST {
  3833				o1 |= 8 /* zero */
  3834				rf = 0
  3835			} else {
  3836				rf = int(p.From.Reg)
  3837			}
  3838			rt := int(p.Reg)
  3839			o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
  3840	
  3841		case 57: /* floating point conditional compare */
  3842			o1 = c.oprrr(p, p.As)
  3843	
  3844			cond := int(p.From.Reg)
  3845			if cond < COND_EQ || cond > COND_NV {
  3846				c.ctxt.Diag("invalid condition\n%v", p)
  3847			} else {
  3848				cond -= COND_EQ
  3849			}
  3850	
  3851			nzcv := int(p.To.Offset)
  3852			if nzcv&^0xF != 0 {
  3853				c.ctxt.Diag("implausible condition\n%v", p)
  3854			}
  3855			rf := int(p.Reg)
  3856			if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
  3857				c.ctxt.Diag("illegal FCCMP\n%v", p)
  3858				break
  3859			}
  3860			rt := int(p.GetFrom3().Reg)
  3861			o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
  3862	
  3863		case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
  3864			o1 = c.opload(p, p.As)
  3865	
  3866			o1 |= 0x1F << 16
  3867			o1 |= uint32(p.From.Reg&31) << 5
  3868			if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
  3869				if int(p.To.Reg) == int(p.To.Offset) {
  3870					c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3871				}
  3872				o1 |= uint32(p.To.Offset&31) << 10
  3873			} else {
  3874				o1 |= 0x1F << 10
  3875			}
  3876			o1 |= uint32(p.To.Reg & 31)
  3877	
  3878		case 59: /* stxr/stlxr/stxp/stlxp */
  3879			s := p.RegTo2
  3880			n := p.To.Reg
  3881			t := p.From.Reg
  3882			if isSTLXRop(p.As) {
  3883				if s == t || (s == n && n != REGSP) {
  3884					c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3885				}
  3886			} else if isSTXPop(p.As) {
  3887				t2 := int16(p.From.Offset)
  3888				if (s == t || s == t2) || (s == n && n != REGSP) {
  3889					c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3890				}
  3891			}
  3892			if s == REG_RSP {
  3893				c.ctxt.Diag("illegal destination register: %v\n", p)
  3894			}
  3895			o1 = c.opstore(p, p.As)
  3896	
  3897			if p.RegTo2 != obj.REG_NONE {
  3898				o1 |= uint32(p.RegTo2&31) << 16
  3899			} else {
  3900				o1 |= 0x1F << 16
  3901			}
  3902			if isSTXPop(p.As) {
  3903				o1 |= uint32(p.From.Offset&31) << 10
  3904			}
  3905			o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
  3906	
  3907		case 60: /* adrp label,r */
  3908			d := c.brdist(p, 12, 21, 0)
  3909	
  3910			o1 = ADR(1, uint32(d), uint32(p.To.Reg))
  3911	
  3912		case 61: /* adr label, r */
  3913			d := c.brdist(p, 0, 21, 0)
  3914	
  3915			o1 = ADR(0, uint32(d), uint32(p.To.Reg))
  3916	
  3917		case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
  3918			if p.Reg == REGTMP {
  3919				c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  3920			}
  3921			if isADDWop(p.As) || isANDWop(p.As) {
  3922				o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
  3923			} else {
  3924				o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
  3925			}
  3926	
  3927			rt := int(p.To.Reg)
  3928			if p.To.Type == obj.TYPE_NONE {
  3929				rt = REGZERO
  3930			}
  3931			r := int(p.Reg)
  3932			if r == 0 {
  3933				r = rt
  3934			}
  3935			if p.To.Reg == REGSP || r == REGSP {
  3936				o2 = c.opxrrr(p, p.As, false)
  3937				o2 |= REGTMP & 31 << 16
  3938				o2 |= LSL0_64
  3939			} else {
  3940				o2 = c.oprrr(p, p.As)
  3941				o2 |= REGTMP & 31 << 16 /* shift is 0 */
  3942			}
  3943			o2 |= uint32(r&31) << 5
  3944			o2 |= uint32(rt & 31)
  3945	
  3946			/* reloc ops */
  3947		case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
  3948			o1 = ADR(1, 0, REGTMP)
  3949			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3950			rel := obj.Addrel(c.cursym)
  3951			rel.Off = int32(c.pc)
  3952			rel.Siz = 8
  3953			rel.Sym = p.To.Sym
  3954			rel.Add = p.To.Offset
  3955			rel.Type = objabi.R_ADDRARM64
  3956			o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
  3957	
  3958		case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
  3959			o1 = ADR(1, 0, REGTMP)
  3960			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3961			rel := obj.Addrel(c.cursym)
  3962			rel.Off = int32(c.pc)
  3963			rel.Siz = 8
  3964			rel.Sym = p.From.Sym
  3965			rel.Add = p.From.Offset
  3966			rel.Type = objabi.R_ADDRARM64
  3967			o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
  3968	
  3969		case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
  3970			v := int32(c.regoff(&p.From))
  3971			r := int(p.From.Reg)
  3972			if r == obj.REG_NONE {
  3973				r = int(o.param)
  3974			}
  3975			if r == obj.REG_NONE {
  3976				c.ctxt.Diag("invalid ldp source: %v\n", p)
  3977			}
  3978			o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  3979	
  3980		case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
  3981			r := int(p.To.Reg)
  3982			if r == obj.REG_NONE {
  3983				r = int(o.param)
  3984			}
  3985			if r == obj.REG_NONE {
  3986				c.ctxt.Diag("invalid stp destination: %v\n", p)
  3987			}
  3988			v := int32(c.regoff(&p.To))
  3989			o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  3990	
  3991		case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
  3992			if p.As == AMOVW {
  3993				c.ctxt.Diag("invalid load of 32-bit address: %v", p)
  3994			}
  3995			o1 = ADR(1, 0, uint32(p.To.Reg))
  3996			o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
  3997			rel := obj.Addrel(c.cursym)
  3998			rel.Off = int32(c.pc)
  3999			rel.Siz = 8
  4000			rel.Sym = p.From.Sym
  4001			rel.Add = p.From.Offset
  4002			rel.Type = objabi.R_ADDRARM64
  4003	
  4004		case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
  4005			o1 = c.opirr(p, AMOVZ)
  4006			o1 |= uint32(p.To.Reg & 31)
  4007			rel := obj.Addrel(c.cursym)
  4008			rel.Off = int32(c.pc)
  4009			rel.Siz = 4
  4010			rel.Sym = p.From.Sym
  4011			rel.Type = objabi.R_ARM64_TLS_LE
  4012			if p.From.Offset != 0 {
  4013				c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4014			}
  4015	
  4016		case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
  4017			o1 = ADR(1, 0, REGTMP)
  4018			o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  4019			rel := obj.Addrel(c.cursym)
  4020			rel.Off = int32(c.pc)
  4021			rel.Siz = 8
  4022			rel.Sym = p.From.Sym
  4023			rel.Add = 0
  4024			rel.Type = objabi.R_ARM64_TLS_IE
  4025			if p.From.Offset != 0 {
  4026				c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4027			}
  4028	
  4029		case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
  4030			o1 = ADR(1, 0, REGTMP)
  4031			o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  4032			rel := obj.Addrel(c.cursym)
  4033			rel.Off = int32(c.pc)
  4034			rel.Siz = 8
  4035			rel.Sym = p.From.Sym
  4036			rel.Add = 0
  4037			rel.Type = objabi.R_ARM64_GOTPCREL
  4038	
  4039		case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls Vm.<T>, Vn.<T>, Vd.<T> */
  4040			af := int((p.From.Reg >> 5) & 15)
  4041			af3 := int((p.Reg >> 5) & 15)
  4042			at := int((p.To.Reg >> 5) & 15)
  4043			if af != af3 || af != at {
  4044				c.ctxt.Diag("operand mismatch: %v", p)
  4045				break
  4046			}
  4047			o1 = c.oprrr(p, p.As)
  4048			rf := int((p.From.Reg) & 31)
  4049			rt := int((p.To.Reg) & 31)
  4050			r := int((p.Reg) & 31)
  4051	
  4052			Q := 0
  4053			size := 0
  4054			switch af {
  4055			case ARNG_16B:
  4056				Q = 1
  4057				size = 0
  4058			case ARNG_2D:
  4059				Q = 1
  4060				size = 3
  4061			case ARNG_2S:
  4062				Q = 0
  4063				size = 2
  4064			case ARNG_4H:
  4065				Q = 0
  4066				size = 1
  4067			case ARNG_4S:
  4068				Q = 1
  4069				size = 2
  4070			case ARNG_8B:
  4071				Q = 0
  4072				size = 0
  4073			case ARNG_8H:
  4074				Q = 1
  4075				size = 1
  4076			default:
  4077				c.ctxt.Diag("invalid arrangement: %v", p)
  4078			}
  4079	
  4080			if (p.As == AVORR || p.As == AVAND || p.As == AVEOR) &&
  4081				(af != ARNG_16B && af != ARNG_8B) {
  4082				c.ctxt.Diag("invalid arrangement: %v", p)
  4083			} else if (p.As == AVFMLA || p.As == AVFMLS) &&
  4084				(af != ARNG_2D && af != ARNG_2S && af != ARNG_4S) {
  4085				c.ctxt.Diag("invalid arrangement: %v", p)
  4086			} else if p.As == AVORR {
  4087				size = 2
  4088			} else if p.As == AVAND || p.As == AVEOR {
  4089				size = 0
  4090			} else if p.As == AVFMLA || p.As == AVFMLS {
  4091				if af == ARNG_2D {
  4092					size = 1
  4093				} else {
  4094					size = 0
  4095				}
  4096			}
  4097	
  4098			o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4099	
  4100		case 73: /* vmov V.<T>[index], R */
  4101			rf := int(p.From.Reg)
  4102			rt := int(p.To.Reg)
  4103			imm5 := 0
  4104			o1 = 7<<25 | 0xf<<10
  4105			index := int(p.From.Index)
  4106			switch (p.From.Reg >> 5) & 15 {
  4107			case ARNG_B:
  4108				c.checkindex(p, index, 15)
  4109				imm5 |= 1
  4110				imm5 |= index << 1
  4111			case ARNG_H:
  4112				c.checkindex(p, index, 7)
  4113				imm5 |= 2
  4114				imm5 |= index << 2
  4115			case ARNG_S:
  4116				c.checkindex(p, index, 3)
  4117				imm5 |= 4
  4118				imm5 |= index << 3
  4119			case ARNG_D:
  4120				c.checkindex(p, index, 1)
  4121				imm5 |= 8
  4122				imm5 |= index << 4
  4123				o1 |= 1 << 30
  4124			default:
  4125				c.ctxt.Diag("invalid arrangement: %v", p)
  4126			}
  4127			o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4128	
  4129		case 74:
  4130			//	add $O, R, Rtmp or sub $O, R, Rtmp
  4131			//	ldp (Rtmp), (R1, R2)
  4132			r := int(p.From.Reg)
  4133			if r == obj.REG_NONE {
  4134				r = int(o.param)
  4135			}
  4136			if r == obj.REG_NONE {
  4137				c.ctxt.Diag("invalid ldp source: %v", p)
  4138			}
  4139			v := int32(c.regoff(&p.From))
  4140	
  4141			if v > 0 {
  4142				if v > 4095 {
  4143					c.ctxt.Diag("offset out of range: %v", p)
  4144				}
  4145				o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  4146			}
  4147			if v < 0 {
  4148				if v < -4095 {
  4149					c.ctxt.Diag("offset out of range: %v", p)
  4150				}
  4151				o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  4152			}
  4153			o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4154	
  4155		case 75:
  4156			//	mov $L, Rtmp (from constant pool)
  4157			//	add Rtmp, R, Rtmp
  4158			//	ldp (Rtmp), (R1, R2)
  4159			r := int(p.From.Reg)
  4160			if r == obj.REG_NONE {
  4161				r = int(o.param)
  4162			}
  4163			if r == obj.REG_NONE {
  4164				c.ctxt.Diag("invalid ldp source: %v", p)
  4165			}
  4166			o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  4167			o2 = c.opxrrr(p, AADD, false)
  4168			o2 |= (REGTMP & 31) << 16
  4169			o2 |= uint32(r&31) << 5
  4170			o2 |= uint32(REGTMP & 31)
  4171			o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4172	
  4173		case 76:
  4174			//	add $O, R, Rtmp or sub $O, R, Rtmp
  4175			//	stp (R1, R2), (Rtmp)
  4176			r := int(p.To.Reg)
  4177			if r == obj.REG_NONE {
  4178				r = int(o.param)
  4179			}
  4180			if r == obj.REG_NONE {
  4181				c.ctxt.Diag("invalid stp destination: %v", p)
  4182			}
  4183			v := int32(c.regoff(&p.To))
  4184			if v > 0 {
  4185				if v > 4095 {
  4186					c.ctxt.Diag("offset out of range: %v", p)
  4187				}
  4188				o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  4189			}
  4190			if v < 0 {
  4191				if v < -4095 {
  4192					c.ctxt.Diag("offset out of range: %v", p)
  4193				}
  4194				o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  4195			}
  4196			o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4197	
  4198		case 77:
  4199			//	mov $L, Rtmp (from constant pool)
  4200			//	add Rtmp, R, Rtmp
  4201			//	stp (R1, R2), (Rtmp)
  4202			r := int(p.To.Reg)
  4203			if r == obj.REG_NONE {
  4204				r = int(o.param)
  4205			}
  4206			if r == obj.REG_NONE {
  4207				c.ctxt.Diag("invalid stp destination: %v", p)
  4208			}
  4209			o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  4210			o2 = c.opxrrr(p, AADD, false)
  4211			o2 |= REGTMP & 31 << 16
  4212			o2 |= uint32(r&31) << 5
  4213			o2 |= uint32(REGTMP & 31)
  4214			o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4215	
  4216		case 78: /* vmov R, V.<T>[index] */
  4217			rf := int(p.From.Reg)
  4218			rt := int(p.To.Reg)
  4219			imm5 := 0
  4220			o1 = 1<<30 | 7<<25 | 7<<10
  4221			index := int(p.To.Index)
  4222			switch (p.To.Reg >> 5) & 15 {
  4223			case ARNG_B:
  4224				c.checkindex(p, index, 15)
  4225				imm5 |= 1
  4226				imm5 |= index << 1
  4227			case ARNG_H:
  4228				c.checkindex(p, index, 7)
  4229				imm5 |= 2
  4230				imm5 |= index << 2
  4231			case ARNG_S:
  4232				c.checkindex(p, index, 3)
  4233				imm5 |= 4
  4234				imm5 |= index << 3
  4235			case ARNG_D:
  4236				c.checkindex(p, index, 1)
  4237				imm5 |= 8
  4238				imm5 |= index << 4
  4239			default:
  4240				c.ctxt.Diag("invalid arrangement: %v", p)
  4241			}
  4242			o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4243	
  4244		case 79: /* vdup Vn.<T>[index], Vd.<T> */
  4245			rf := int(p.From.Reg)
  4246			rt := int(p.To.Reg)
  4247			o1 = 7<<25 | 1<<10
  4248			var imm5, Q int
  4249			index := int(p.From.Index)
  4250			switch (p.To.Reg >> 5) & 15 {
  4251			case ARNG_16B:
  4252				c.checkindex(p, index, 15)
  4253				Q = 1
  4254				imm5 = 1
  4255				imm5 |= index << 1
  4256			case ARNG_2D:
  4257				c.checkindex(p, index, 1)
  4258				Q = 1
  4259				imm5 = 8
  4260				imm5 |= index << 4
  4261			case ARNG_2S:
  4262				c.checkindex(p, index, 3)
  4263				Q = 0
  4264				imm5 = 4
  4265				imm5 |= index << 3
  4266			case ARNG_4H:
  4267				c.checkindex(p, index, 7)
  4268				Q = 0
  4269				imm5 = 2
  4270				imm5 |= index << 2
  4271			case ARNG_4S:
  4272				c.checkindex(p, index, 3)
  4273				Q = 1
  4274				imm5 = 4
  4275				imm5 |= index << 3
  4276			case ARNG_8B:
  4277				c.checkindex(p, index, 15)
  4278				Q = 0
  4279				imm5 = 1
  4280				imm5 |= index << 1
  4281			case ARNG_8H:
  4282				c.checkindex(p, index, 7)
  4283				Q = 1
  4284				imm5 = 2
  4285				imm5 |= index << 2
  4286			default:
  4287				c.ctxt.Diag("invalid arrangement: %v", p)
  4288			}
  4289			o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  4290			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4291	
  4292		case 80: /* vmov V.<T>[index], Vn */
  4293			rf := int(p.From.Reg)
  4294			rt := int(p.To.Reg)
  4295			imm5 := 0
  4296			index := int(p.From.Index)
  4297			switch p.As {
  4298			case AVMOV:
  4299				o1 = 1<<30 | 15<<25 | 1<<10
  4300				switch (p.From.Reg >> 5) & 15 {
  4301				case ARNG_B:
  4302					c.checkindex(p, index, 15)
  4303					imm5 |= 1
  4304					imm5 |= index << 1
  4305				case ARNG_H:
  4306					c.checkindex(p, index, 7)
  4307					imm5 |= 2
  4308					imm5 |= index << 2
  4309				case ARNG_S:
  4310					c.checkindex(p, index, 3)
  4311					imm5 |= 4
  4312					imm5 |= index << 3
  4313				case ARNG_D:
  4314					c.checkindex(p, index, 1)
  4315					imm5 |= 8
  4316					imm5 |= index << 4
  4317				default:
  4318					c.ctxt.Diag("invalid arrangement: %v", p)
  4319				}
  4320			default:
  4321				c.ctxt.Diag("unsupported op %v", p.As)
  4322			}
  4323			o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4324	
  4325		case 81: /* vld1 (Rn), [Vt1.<T>, Vt2.<T>, ...] */
  4326			r := int(p.From.Reg)
  4327			o1 = 3<<26 | 1<<22
  4328			if o.scond == C_XPOST {
  4329				o1 |= 1 << 23
  4330				if p.From.Index == 0 {
  4331					// immediate offset variant
  4332					c.checkoffset(p, p.As)
  4333					o1 |= 0x1f << 16
  4334				} else {
  4335					// register offset variant
  4336					if isRegShiftOrExt(&p.From) {
  4337						c.ctxt.Diag("invalid extended register op: %v\n", p)
  4338					}
  4339					o1 |= uint32(p.From.Index&31) << 16
  4340				}
  4341			}
  4342			o1 |= uint32(p.To.Offset)
  4343			o1 |= uint32(r&31) << 5
  4344	
  4345		case 82: /* vmov Rn, Vd.<T> */
  4346			rf := int(p.From.Reg)
  4347			rt := int(p.To.Reg)
  4348			o1 = 7<<25 | 3<<10
  4349			var imm5, Q uint32
  4350			switch (p.To.Reg >> 5) & 15 {
  4351			case ARNG_16B:
  4352				Q = 1
  4353				imm5 = 1
  4354			case ARNG_2D:
  4355				Q = 1
  4356				imm5 = 8
  4357			case ARNG_2S:
  4358				Q = 0
  4359				imm5 = 4
  4360			case ARNG_4H:
  4361				Q = 0
  4362				imm5 = 2
  4363			case ARNG_4S:
  4364				Q = 1
  4365				imm5 = 4
  4366			case ARNG_8B:
  4367				Q = 0
  4368				imm5 = 1
  4369			case ARNG_8H:
  4370				Q = 1
  4371				imm5 = 2
  4372			default:
  4373				c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p)
  4374			}
  4375			o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
  4376			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4377	
  4378		case 83: /* vmov Vn.<T>, Vd.<T> */
  4379			af := int((p.From.Reg >> 5) & 15)
  4380			at := int((p.To.Reg >> 5) & 15)
  4381			if af != at {
  4382				c.ctxt.Diag("invalid arrangement: %v\n", p)
  4383			}
  4384			o1 = c.oprrr(p, p.As)
  4385			rf := int((p.From.Reg) & 31)
  4386			rt := int((p.To.Reg) & 31)
  4387	
  4388			var Q, size uint32
  4389			switch af {
  4390			case ARNG_8B:
  4391				Q = 0
  4392				size = 0
  4393			case ARNG_16B:
  4394				Q = 1
  4395				size = 0
  4396			case ARNG_4H:
  4397				Q = 0
  4398				size = 1
  4399			case ARNG_8H:
  4400				Q = 1
  4401				size = 1
  4402			case ARNG_2S:
  4403				Q = 0
  4404				size = 2
  4405			case ARNG_4S:
  4406				Q = 1
  4407				size = 2
  4408			default:
  4409				c.ctxt.Diag("invalid arrangement: %v\n", p)
  4410			}
  4411	
  4412			if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) {
  4413				c.ctxt.Diag("invalid arrangement: %v", p)
  4414			}
  4415	
  4416			if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
  4417				c.ctxt.Diag("invalid arrangement: %v", p)
  4418			}
  4419	
  4420			if p.As == AVMOV {
  4421				o1 |= uint32(rf&31) << 16
  4422			}
  4423	
  4424			if p.As == AVRBIT {
  4425				size = 1
  4426			}
  4427	
  4428			o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
  4429	
  4430		case 84: /* vst1 [Vt1.<T>, Vt2.<T>, ...], (Rn) */
  4431			r := int(p.To.Reg)
  4432			o1 = 3 << 26
  4433			if o.scond == C_XPOST {
  4434				o1 |= 1 << 23
  4435				if p.To.Index == 0 {
  4436					// immediate offset variant
  4437					c.checkoffset(p, p.As)
  4438					o1 |= 0x1f << 16
  4439				} else {
  4440					// register offset variant
  4441					if isRegShiftOrExt(&p.To) {
  4442						c.ctxt.Diag("invalid extended register: %v\n", p)
  4443					}
  4444					o1 |= uint32(p.To.Index&31) << 16
  4445				}
  4446			}
  4447			o1 |= uint32(p.From.Offset)
  4448			o1 |= uint32(r&31) << 5
  4449	
  4450		case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
  4451			af := int((p.From.Reg >> 5) & 15)
  4452			o1 = c.oprrr(p, p.As)
  4453			rf := int((p.From.Reg) & 31)
  4454			rt := int((p.To.Reg) & 31)
  4455			Q := 0
  4456			size := 0
  4457			switch af {
  4458			case ARNG_8B:
  4459				Q = 0
  4460				size = 0
  4461			case ARNG_16B:
  4462				Q = 1
  4463				size = 0
  4464			case ARNG_4H:
  4465				Q = 0
  4466				size = 1
  4467			case ARNG_8H:
  4468				Q = 1
  4469				size = 1
  4470			case ARNG_4S:
  4471				Q = 1
  4472				size = 2
  4473			default:
  4474				c.ctxt.Diag("invalid arrangement: %v\n", p)
  4475			}
  4476			o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
  4477	
  4478		case 86: /* vmovi $imm8, Vd.<T>*/
  4479			at := int((p.To.Reg >> 5) & 15)
  4480			r := int(p.From.Offset)
  4481			if r > 255 || r < 0 {
  4482				c.ctxt.Diag("immediate constant out of range: %v\n", p)
  4483			}
  4484			rt := int((p.To.Reg) & 31)
  4485			Q := 0
  4486			switch at {
  4487			case ARNG_8B:
  4488				Q = 0
  4489			case ARNG_16B:
  4490				Q = 1
  4491			default:
  4492				c.ctxt.Diag("invalid arrangement: %v\n", p)
  4493			}
  4494			o1 = 0xf<<24 | 0xe<<12 | 1<<10
  4495			o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
  4496	
  4497		case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
  4498			o1 = ADR(1, 0, REGTMP)
  4499			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4500			rel := obj.Addrel(c.cursym)
  4501			rel.Off = int32(c.pc)
  4502			rel.Siz = 8
  4503			rel.Sym = p.To.Sym
  4504			rel.Add = p.To.Offset
  4505			rel.Type = objabi.R_ADDRARM64
  4506			o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4507	
  4508		case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
  4509			o1 = ADR(1, 0, REGTMP)
  4510			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4511			rel := obj.Addrel(c.cursym)
  4512			rel.Off = int32(c.pc)
  4513			rel.Siz = 8
  4514			rel.Sym = p.From.Sym
  4515			rel.Add = p.From.Offset
  4516			rel.Type = objabi.R_ADDRARM64
  4517			o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4518	
  4519		case 89: /* vadd/vsub Vm, Vn, Vd */
  4520			switch p.As {
  4521			case AVADD:
  4522				o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4523	
  4524			case AVSUB:
  4525				o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4526	
  4527			default:
  4528				c.ctxt.Diag("bad opcode: %v\n", p)
  4529				break
  4530			}
  4531	
  4532			rf := int(p.From.Reg)
  4533			rt := int(p.To.Reg)
  4534			r := int(p.Reg)
  4535			if r == 0 {
  4536				r = rt
  4537			}
  4538			o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4539	
  4540		// This is supposed to be something that stops execution.
  4541		// It's not supposed to be reached, ever, but if it is, we'd
  4542		// like to be able to tell how we got there. Assemble as
  4543		// 0xbea71700 which is guaranteed to raise undefined instruction
  4544		// exception.
  4545		case 90:
  4546			o1 = 0xbea71700
  4547	
  4548		case 91: /* prfm imm(Rn), <prfop | $imm5> */
  4549			imm := uint32(p.From.Offset)
  4550			r := p.From.Reg
  4551			v := uint32(0xff)
  4552			if p.To.Type == obj.TYPE_CONST {
  4553				v = uint32(p.To.Offset)
  4554				if v > 31 {
  4555					c.ctxt.Diag("illegal prefetch operation\n%v", p)
  4556				}
  4557			} else {
  4558				for i := 0; i < len(prfopfield); i++ {
  4559					if prfopfield[i].reg == p.To.Reg {
  4560						v = prfopfield[i].enc
  4561						break
  4562					}
  4563				}
  4564				if v == 0xff {
  4565					c.ctxt.Diag("illegal prefetch operation:\n%v", p)
  4566				}
  4567			}
  4568	
  4569			o1 = c.opldrpp(p, p.As)
  4570			o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
  4571	
  4572		case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
  4573			rf := int(p.From.Reg)
  4574			rt := int(p.To.Reg)
  4575			imm4 := 0
  4576			imm5 := 0
  4577			o1 = 3<<29 | 7<<25 | 1<<10
  4578			index1 := int(p.To.Index)
  4579			index2 := int(p.From.Index)
  4580			if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
  4581				c.ctxt.Diag("operand mismatch: %v", p)
  4582			}
  4583			switch (p.To.Reg >> 5) & 15 {
  4584			case ARNG_B:
  4585				c.checkindex(p, index1, 15)
  4586				c.checkindex(p, index2, 15)
  4587				imm5 |= 1
  4588				imm5 |= index1 << 1
  4589				imm4 |= index2
  4590			case ARNG_H:
  4591				c.checkindex(p, index1, 7)
  4592				c.checkindex(p, index2, 7)
  4593				imm5 |= 2
  4594				imm5 |= index1 << 2
  4595				imm4 |= index2 << 1
  4596			case ARNG_S:
  4597				c.checkindex(p, index1, 3)
  4598				c.checkindex(p, index2, 3)
  4599				imm5 |= 4
  4600				imm5 |= index1 << 3
  4601				imm4 |= index2 << 2
  4602			case ARNG_D:
  4603				c.checkindex(p, index1, 1)
  4604				c.checkindex(p, index2, 1)
  4605				imm5 |= 8
  4606				imm5 |= index1 << 4
  4607				imm4 |= index2 << 3
  4608			default:
  4609				c.ctxt.Diag("invalid arrangement: %v", p)
  4610			}
  4611			o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  4612	
  4613		case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */
  4614			af := int((p.From.Reg >> 5) & 15)
  4615			at := int((p.To.Reg >> 5) & 15)
  4616			a := int((p.Reg >> 5) & 15)
  4617	
  4618			var Q, size uint32
  4619			if p.As == AVPMULL {
  4620				Q = 0
  4621			} else {
  4622				Q = 1
  4623			}
  4624	
  4625			var fArng int
  4626			switch at {
  4627			case ARNG_8H:
  4628				if Q == 0 {
  4629					fArng = ARNG_8B
  4630				} else {
  4631					fArng = ARNG_16B
  4632				}
  4633				size = 0
  4634			case ARNG_1Q:
  4635				if Q == 0 {
  4636					fArng = ARNG_1D
  4637				} else {
  4638					fArng = ARNG_2D
  4639				}
  4640				size = 3
  4641			default:
  4642				c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p)
  4643			}
  4644	
  4645			if af != a || af != fArng {
  4646				c.ctxt.Diag("invalid arrangement: %v", p)
  4647			}
  4648	
  4649			o1 = c.oprrr(p, p.As)
  4650			rf := int((p.From.Reg) & 31)
  4651			rt := int((p.To.Reg) & 31)
  4652			r := int((p.Reg) & 31)
  4653	
  4654			o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4655	
  4656		case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  4657			af := int(((p.GetFrom3().Reg) >> 5) & 15)
  4658			at := int((p.To.Reg >> 5) & 15)
  4659			a := int((p.Reg >> 5) & 15)
  4660			index := int(p.From.Offset)
  4661	
  4662			if af != a || af != at {
  4663				c.ctxt.Diag("invalid arrangement: %v", p)
  4664				break
  4665			}
  4666	
  4667			var Q uint32
  4668			var b int
  4669			if af == ARNG_8B {
  4670				Q = 0
  4671				b = 7
  4672			} else if af == ARNG_16B {
  4673				Q = 1
  4674				b = 15
  4675			} else {
  4676				c.ctxt.Diag("invalid arrangement, should be 8B or 16B: %v", p)
  4677				break
  4678			}
  4679	
  4680			if index < 0 || index > b {
  4681				c.ctxt.Diag("illegal offset: %v", p)
  4682			}
  4683	
  4684			o1 = c.opirr(p, p.As)
  4685			rf := int((p.GetFrom3().Reg) & 31)
  4686			rt := int((p.To.Reg) & 31)
  4687			r := int((p.Reg) & 31)
  4688	
  4689			o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  4690	
  4691		case 95: /* vushr $shift, Vn.<T>, Vd.<T> */
  4692			at := int((p.To.Reg >> 5) & 15)
  4693			af := int((p.Reg >> 5) & 15)
  4694			shift := int(p.From.Offset)
  4695	
  4696			if af != at {
  4697				c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  4698			}
  4699	
  4700			var Q uint32
  4701			var imax, esize int
  4702	
  4703			switch af {
  4704			case ARNG_8B, ARNG_4H, ARNG_2S:
  4705				Q = 0
  4706			case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
  4707				Q = 1
  4708			default:
  4709				c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  4710			}
  4711	
  4712			switch af {
  4713			case ARNG_8B, ARNG_16B:
  4714				imax = 15
  4715				esize = 8
  4716			case ARNG_4H, ARNG_8H:
  4717				imax = 31
  4718				esize = 16
  4719			case ARNG_2S, ARNG_4S:
  4720				imax = 63
  4721				esize = 32
  4722			case ARNG_2D:
  4723				imax = 127
  4724				esize = 64
  4725			}
  4726	
  4727			imm := 0
  4728	
  4729			switch p.As {
  4730			case AVUSHR, AVSRI:
  4731				imm = esize*2 - shift
  4732				if imm < esize || imm > imax {
  4733					c.ctxt.Diag("shift out of range: %v", p)
  4734				}
  4735			case AVSHL:
  4736				imm = esize + shift
  4737				if imm > imax {
  4738					c.ctxt.Diag("shift out of range: %v", p)
  4739				}
  4740			default:
  4741				c.ctxt.Diag("invalid instruction %v\n", p)
  4742			}
  4743	
  4744			o1 = c.opirr(p, p.As)
  4745			rt := int((p.To.Reg) & 31)
  4746			rf := int((p.Reg) & 31)
  4747	
  4748			o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4749	
  4750		case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
  4751			af := int((p.From.Reg >> 5) & 15)
  4752			rt := int((p.From.Reg) & 31)
  4753			rf := int((p.To.Reg) & 31)
  4754			r := int(p.To.Index & 31)
  4755			index := int(p.From.Index)
  4756			offset := int32(c.regoff(&p.To))
  4757	
  4758			if o.scond == C_XPOST {
  4759				if (p.To.Index != 0) && (offset != 0) {
  4760					c.ctxt.Diag("invalid offset: %v", p)
  4761				}
  4762				if p.To.Index == 0 && offset == 0 {
  4763					c.ctxt.Diag("invalid offset: %v", p)
  4764				}
  4765			}
  4766	
  4767			if offset != 0 {
  4768				r = 31
  4769			}
  4770	
  4771			var Q, S, size int
  4772			var opcode uint32
  4773			switch af {
  4774			case ARNG_B:
  4775				c.checkindex(p, index, 15)
  4776				if o.scond == C_XPOST && offset != 0 && offset != 1 {
  4777					c.ctxt.Diag("invalid offset: %v", p)
  4778				}
  4779				Q = index >> 3
  4780				S = (index >> 2) & 1
  4781				size = index & 3
  4782				opcode = 0
  4783			case ARNG_H:
  4784				c.checkindex(p, index, 7)
  4785				if o.scond == C_XPOST && offset != 0 && offset != 2 {
  4786					c.ctxt.Diag("invalid offset: %v", p)
  4787				}
  4788				Q = index >> 2
  4789				S = (index >> 1) & 1
  4790				size = (index & 1) << 1
  4791				opcode = 2
  4792			case ARNG_S:
  4793				c.checkindex(p, index, 3)
  4794				if o.scond == C_XPOST && offset != 0 && offset != 4 {
  4795					c.ctxt.Diag("invalid offset: %v", p)
  4796				}
  4797				Q = index >> 1
  4798				S = index & 1
  4799				size = 0
  4800				opcode = 4
  4801			case ARNG_D:
  4802				c.checkindex(p, index, 1)
  4803				if o.scond == C_XPOST && offset != 0 && offset != 8 {
  4804					c.ctxt.Diag("invalid offset: %v", p)
  4805				}
  4806				Q = index
  4807				S = 0
  4808				size = 1
  4809				opcode = 4
  4810			default:
  4811				c.ctxt.Diag("invalid arrangement: %v", p)
  4812			}
  4813	
  4814			if o.scond == C_XPOST {
  4815				o1 |= 27 << 23
  4816			} else {
  4817				o1 |= 26 << 23
  4818			}
  4819	
  4820			o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  4821	
  4822		case 97: /* vld1 offset(Rn), vt.<T>[index] */
  4823			at := int((p.To.Reg >> 5) & 15)
  4824			rt := int((p.To.Reg) & 31)
  4825			rf := int((p.From.Reg) & 31)
  4826			r := int(p.From.Index & 31)
  4827			index := int(p.To.Index)
  4828			offset := int32(c.regoff(&p.From))
  4829	
  4830			if o.scond == C_XPOST {
  4831				if (p.From.Index != 0) && (offset != 0) {
  4832					c.ctxt.Diag("invalid offset: %v", p)
  4833				}
  4834				if p.From.Index == 0 && offset == 0 {
  4835					c.ctxt.Diag("invalid offset: %v", p)
  4836				}
  4837			}
  4838	
  4839			if offset != 0 {
  4840				r = 31
  4841			}
  4842	
  4843			Q := 0
  4844			S := 0
  4845			size := 0
  4846			var opcode uint32
  4847			switch at {
  4848			case ARNG_B:
  4849				c.checkindex(p, index, 15)
  4850				if o.scond == C_XPOST && offset != 0 && offset != 1 {
  4851					c.ctxt.Diag("invalid offset: %v", p)
  4852				}
  4853				Q = index >> 3
  4854				S = (index >> 2) & 1
  4855				size = index & 3
  4856				opcode = 0
  4857			case ARNG_H:
  4858				c.checkindex(p, index, 7)
  4859				if o.scond == C_XPOST && offset != 0 && offset != 2 {
  4860					c.ctxt.Diag("invalid offset: %v", p)
  4861				}
  4862				Q = index >> 2
  4863				S = (index >> 1) & 1
  4864				size = (index & 1) << 1
  4865				opcode = 2
  4866			case ARNG_S:
  4867				c.checkindex(p, index, 3)
  4868				if o.scond == C_XPOST && offset != 0 && offset != 4 {
  4869					c.ctxt.Diag("invalid offset: %v", p)
  4870				}
  4871				Q = index >> 1
  4872				S = index & 1
  4873				size = 0
  4874				opcode = 4
  4875			case ARNG_D:
  4876				c.checkindex(p, index, 1)
  4877				if o.scond == C_XPOST && offset != 0 && offset != 8 {
  4878					c.ctxt.Diag("invalid offset: %v", p)
  4879				}
  4880				Q = index
  4881				S = 0
  4882				size = 1
  4883				opcode = 4
  4884			default:
  4885				c.ctxt.Diag("invalid arrangement: %v", p)
  4886			}
  4887	
  4888			if o.scond == C_XPOST {
  4889				o1 |= 110 << 21
  4890			} else {
  4891				o1 |= 106 << 21
  4892			}
  4893	
  4894			o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  4895	
  4896		case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
  4897			if isRegShiftOrExt(&p.From) {
  4898				// extended or shifted offset register.
  4899				c.checkShiftAmount(p, &p.From)
  4900	
  4901				o1 = c.opldrr(p, p.As, true)
  4902				o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
  4903			} else {
  4904				// (Rn)(Rm), no extension or shift.
  4905				o1 = c.opldrr(p, p.As, false)
  4906				o1 |= uint32(p.From.Index&31) << 16
  4907			}
  4908			o1 |= uint32(p.From.Reg&31) << 5
  4909			rt := int(p.To.Reg)
  4910			o1 |= uint32(rt & 31)
  4911	
  4912		case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
  4913			if isRegShiftOrExt(&p.To) {
  4914				// extended or shifted offset register.
  4915				c.checkShiftAmount(p, &p.To)
  4916	
  4917				o1 = c.opstrr(p, p.As, true)
  4918				o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
  4919			} else {
  4920				// (Rn)(Rm), no extension or shift.
  4921				o1 = c.opstrr(p, p.As, false)
  4922				o1 |= uint32(p.To.Index&31) << 16
  4923			}
  4924			o1 |= uint32(p.To.Reg&31) << 5
  4925			rf := int(p.From.Reg)
  4926			o1 |= uint32(rf & 31)
  4927	
  4928		case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
  4929			af := int((p.From.Reg >> 5) & 15)
  4930			at := int((p.To.Reg >> 5) & 15)
  4931			if af != at {
  4932				c.ctxt.Diag("invalid arrangement: %v\n", p)
  4933			}
  4934			var q, len uint32
  4935			switch af {
  4936			case ARNG_8B:
  4937				q = 0
  4938			case ARNG_16B:
  4939				q = 1
  4940			default:
  4941				c.ctxt.Diag("invalid arrangement: %v", p)
  4942			}
  4943			rf := int(p.From.Reg)
  4944			rt := int(p.To.Reg)
  4945			offset := int(p.GetFrom3().Offset)
  4946			opcode := (offset >> 12) & 15
  4947			switch opcode {
  4948			case 0x7:
  4949				len = 0 // one register
  4950			case 0xa:
  4951				len = 1 // two register
  4952			case 0x6:
  4953				len = 2 // three registers
  4954			case 0x2:
  4955				len = 3 // four registers
  4956			default:
  4957				c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  4958			}
  4959			o1 = q<<30 | 0xe<<24 | len<<13
  4960			o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
  4961	
  4962		}
  4963		out[0] = o1
  4964		out[1] = o2
  4965		out[2] = o3
  4966		out[3] = o4
  4967		out[4] = o5
  4968	}
  4969	
  4970	/*
  4971	 * basic Rm op Rn -> Rd (using shifted register with 0)
  4972	 * also op Rn -> Rt
  4973	 * also Rm*Rn op Ra -> Rd
  4974	 * also Vm op Vn -> Vd
  4975	 */
  4976	func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
  4977		switch a {
  4978		case AADC:
  4979			return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4980	
  4981		case AADCW:
  4982			return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4983	
  4984		case AADCS:
  4985			return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4986	
  4987		case AADCSW:
  4988			return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4989	
  4990		case ANGC, ASBC:
  4991			return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4992	
  4993		case ANGCS, ASBCS:
  4994			return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4995	
  4996		case ANGCW, ASBCW:
  4997			return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4998	
  4999		case ANGCSW, ASBCSW:
  5000			return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5001	
  5002		case AADD:
  5003			return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5004	
  5005		case AADDW:
  5006			return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5007	
  5008		case ACMN, AADDS:
  5009			return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5010	
  5011		case ACMNW, AADDSW:
  5012			return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5013	
  5014		case ASUB:
  5015			return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5016	
  5017		case ASUBW:
  5018			return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5019	
  5020		case ACMP, ASUBS:
  5021			return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5022	
  5023		case ACMPW, ASUBSW:
  5024			return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5025	
  5026		case AAND:
  5027			return S64 | 0<<29 | 0xA<<24
  5028	
  5029		case AANDW:
  5030			return S32 | 0<<29 | 0xA<<24
  5031	
  5032		case AMOVD, AORR:
  5033			return S64 | 1<<29 | 0xA<<24
  5034	
  5035			//	case AMOVW:
  5036		case AMOVWU, AORRW:
  5037			return S32 | 1<<29 | 0xA<<24
  5038	
  5039		case AEOR:
  5040			return S64 | 2<<29 | 0xA<<24
  5041	
  5042		case AEORW:
  5043			return S32 | 2<<29 | 0xA<<24
  5044	
  5045		case AANDS, ATST:
  5046			return S64 | 3<<29 | 0xA<<24
  5047	
  5048		case AANDSW, ATSTW:
  5049			return S32 | 3<<29 | 0xA<<24
  5050	
  5051		case ABIC:
  5052			return S64 | 0<<29 | 0xA<<24 | 1<<21
  5053	
  5054		case ABICW:
  5055			return S32 | 0<<29 | 0xA<<24 | 1<<21
  5056	
  5057		case ABICS:
  5058			return S64 | 3<<29 | 0xA<<24 | 1<<21
  5059	
  5060		case ABICSW:
  5061			return S32 | 3<<29 | 0xA<<24 | 1<<21
  5062	
  5063		case AEON:
  5064			return S64 | 2<<29 | 0xA<<24 | 1<<21
  5065	
  5066		case AEONW:
  5067			return S32 | 2<<29 | 0xA<<24 | 1<<21
  5068	
  5069		case AMVN, AORN:
  5070			return S64 | 1<<29 | 0xA<<24 | 1<<21
  5071	
  5072		case AMVNW, AORNW:
  5073			return S32 | 1<<29 | 0xA<<24 | 1<<21
  5074	
  5075		case AASR:
  5076			return S64 | OPDP2(10) /* also ASRV */
  5077	
  5078		case AASRW:
  5079			return S32 | OPDP2(10)
  5080	
  5081		case ALSL:
  5082			return S64 | OPDP2(8)
  5083	
  5084		case ALSLW:
  5085			return S32 | OPDP2(8)
  5086	
  5087		case ALSR:
  5088			return S64 | OPDP2(9)
  5089	
  5090		case ALSRW:
  5091			return S32 | OPDP2(9)
  5092	
  5093		case AROR:
  5094			return S64 | OPDP2(11)
  5095	
  5096		case ARORW:
  5097			return S32 | OPDP2(11)
  5098	
  5099		case ACCMN:
  5100			return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
  5101	
  5102		case ACCMNW:
  5103			return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5104	
  5105		case ACCMP:
  5106			return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5107	
  5108		case ACCMPW:
  5109			return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5110	
  5111		case ACRC32B:
  5112			return S32 | OPDP2(16)
  5113	
  5114		case ACRC32H:
  5115			return S32 | OPDP2(17)
  5116	
  5117		case ACRC32W:
  5118			return S32 | OPDP2(18)
  5119	
  5120		case ACRC32X:
  5121			return S64 | OPDP2(19)
  5122	
  5123		case ACRC32CB:
  5124			return S32 | OPDP2(20)
  5125	
  5126		case ACRC32CH:
  5127			return S32 | OPDP2(21)
  5128	
  5129		case ACRC32CW:
  5130			return S32 | OPDP2(22)
  5131	
  5132		case ACRC32CX:
  5133			return S64 | OPDP2(23)
  5134	
  5135		case ACSEL:
  5136			return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5137	
  5138		case ACSELW:
  5139			return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5140	
  5141		case ACSET:
  5142			return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5143	
  5144		case ACSETW:
  5145			return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5146	
  5147		case ACSETM:
  5148			return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5149	
  5150		case ACSETMW:
  5151			return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5152	
  5153		case ACINC, ACSINC:
  5154			return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5155	
  5156		case ACINCW, ACSINCW:
  5157			return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5158	
  5159		case ACINV, ACSINV:
  5160			return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5161	
  5162		case ACINVW, ACSINVW:
  5163			return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5164	
  5165		case ACNEG, ACSNEG:
  5166			return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5167	
  5168		case ACNEGW, ACSNEGW:
  5169			return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5170	
  5171		case AMUL, AMADD:
  5172			return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  5173	
  5174		case AMULW, AMADDW:
  5175			return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  5176	
  5177		case AMNEG, AMSUB:
  5178			return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  5179	
  5180		case AMNEGW, AMSUBW:
  5181			return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  5182	
  5183		case AMRS:
  5184			return SYSOP(1, 2, 0, 0, 0, 0, 0)
  5185	
  5186		case AMSR:
  5187			return SYSOP(0, 2, 0, 0, 0, 0, 0)
  5188	
  5189		case ANEG:
  5190			return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  5191	
  5192		case ANEGW:
  5193			return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  5194	
  5195		case ANEGS:
  5196			return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  5197	
  5198		case ANEGSW:
  5199			return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  5200	
  5201		case AREM, ASDIV:
  5202			return S64 | OPDP2(3)
  5203	
  5204		case AREMW, ASDIVW:
  5205			return S32 | OPDP2(3)
  5206	
  5207		case ASMULL, ASMADDL:
  5208			return OPDP3(1, 0, 1, 0)
  5209	
  5210		case ASMNEGL, ASMSUBL:
  5211			return OPDP3(1, 0, 1, 1)
  5212	
  5213		case ASMULH:
  5214			return OPDP3(1, 0, 2, 0)
  5215	
  5216		case AUMULL, AUMADDL:
  5217			return OPDP3(1, 0, 5, 0)
  5218	
  5219		case AUMNEGL, AUMSUBL:
  5220			return OPDP3(1, 0, 5, 1)
  5221	
  5222		case AUMULH:
  5223			return OPDP3(1, 0, 6, 0)
  5224	
  5225		case AUREM, AUDIV:
  5226			return S64 | OPDP2(2)
  5227	
  5228		case AUREMW, AUDIVW:
  5229			return S32 | OPDP2(2)
  5230	
  5231		case AAESE:
  5232			return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
  5233	
  5234		case AAESD:
  5235			return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
  5236	
  5237		case AAESMC:
  5238			return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
  5239	
  5240		case AAESIMC:
  5241			return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
  5242	
  5243		case ASHA1C:
  5244			return 0x5E<<24 | 0<<12
  5245	
  5246		case ASHA1P:
  5247			return 0x5E<<24 | 1<<12
  5248	
  5249		case ASHA1M:
  5250			return 0x5E<<24 | 2<<12
  5251	
  5252		case ASHA1SU0:
  5253			return 0x5E<<24 | 3<<12
  5254	
  5255		case ASHA256H:
  5256			return 0x5E<<24 | 4<<12
  5257	
  5258		case ASHA256H2:
  5259			return 0x5E<<24 | 5<<12
  5260	
  5261		case ASHA256SU1:
  5262			return 0x5E<<24 | 6<<12
  5263	
  5264		case ASHA1H:
  5265			return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
  5266	
  5267		case ASHA1SU1:
  5268			return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
  5269	
  5270		case ASHA256SU0:
  5271			return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
  5272	
  5273		case AFCVTZSD:
  5274			return FPCVTI(1, 0, 1, 3, 0)
  5275	
  5276		case AFCVTZSDW:
  5277			return FPCVTI(0, 0, 1, 3, 0)
  5278	
  5279		case AFCVTZSS:
  5280			return FPCVTI(1, 0, 0, 3, 0)
  5281	
  5282		case AFCVTZSSW:
  5283			return FPCVTI(0, 0, 0, 3, 0)
  5284	
  5285		case AFCVTZUD:
  5286			return FPCVTI(1, 0, 1, 3, 1)
  5287	
  5288		case AFCVTZUDW:
  5289			return FPCVTI(0, 0, 1, 3, 1)
  5290	
  5291		case AFCVTZUS:
  5292			return FPCVTI(1, 0, 0, 3, 1)
  5293	
  5294		case AFCVTZUSW:
  5295			return FPCVTI(0, 0, 0, 3, 1)
  5296	
  5297		case ASCVTFD:
  5298			return FPCVTI(1, 0, 1, 0, 2)
  5299	
  5300		case ASCVTFS:
  5301			return FPCVTI(1, 0, 0, 0, 2)
  5302	
  5303		case ASCVTFWD:
  5304			return FPCVTI(0, 0, 1, 0, 2)
  5305	
  5306		case ASCVTFWS:
  5307			return FPCVTI(0, 0, 0, 0, 2)
  5308	
  5309		case AUCVTFD:
  5310			return FPCVTI(1, 0, 1, 0, 3)
  5311	
  5312		case AUCVTFS:
  5313			return FPCVTI(1, 0, 0, 0, 3)
  5314	
  5315		case AUCVTFWD:
  5316			return FPCVTI(0, 0, 1, 0, 3)
  5317	
  5318		case AUCVTFWS:
  5319			return FPCVTI(0, 0, 0, 0, 3)
  5320	
  5321		case AFADDS:
  5322			return FPOP2S(0, 0, 0, 2)
  5323	
  5324		case AFADDD:
  5325			return FPOP2S(0, 0, 1, 2)
  5326	
  5327		case AFSUBS:
  5328			return FPOP2S(0, 0, 0, 3)
  5329	
  5330		case AFSUBD:
  5331			return FPOP2S(0, 0, 1, 3)
  5332	
  5333		case AFMADDD:
  5334			return FPOP3S(0, 0, 1, 0, 0)
  5335	
  5336		case AFMADDS:
  5337			return FPOP3S(0, 0, 0, 0, 0)
  5338	
  5339		case AFMSUBD:
  5340			return FPOP3S(0, 0, 1, 0, 1)
  5341	
  5342		case AFMSUBS:
  5343			return FPOP3S(0, 0, 0, 0, 1)
  5344	
  5345		case AFNMADDD:
  5346			return FPOP3S(0, 0, 1, 1, 0)
  5347	
  5348		case AFNMADDS:
  5349			return FPOP3S(0, 0, 0, 1, 0)
  5350	
  5351		case AFNMSUBD:
  5352			return FPOP3S(0, 0, 1, 1, 1)
  5353	
  5354		case AFNMSUBS:
  5355			return FPOP3S(0, 0, 0, 1, 1)
  5356	
  5357		case AFMULS:
  5358			return FPOP2S(0, 0, 0, 0)
  5359	
  5360		case AFMULD:
  5361			return FPOP2S(0, 0, 1, 0)
  5362	
  5363		case AFDIVS:
  5364			return FPOP2S(0, 0, 0, 1)
  5365	
  5366		case AFDIVD:
  5367			return FPOP2S(0, 0, 1, 1)
  5368	
  5369		case AFMAXS:
  5370			return FPOP2S(0, 0, 0, 4)
  5371	
  5372		case AFMINS:
  5373			return FPOP2S(0, 0, 0, 5)
  5374	
  5375		case AFMAXD:
  5376			return FPOP2S(0, 0, 1, 4)
  5377	
  5378		case AFMIND:
  5379			return FPOP2S(0, 0, 1, 5)
  5380	
  5381		case AFMAXNMS:
  5382			return FPOP2S(0, 0, 0, 6)
  5383	
  5384		case AFMAXNMD:
  5385			return FPOP2S(0, 0, 1, 6)
  5386	
  5387		case AFMINNMS:
  5388			return FPOP2S(0, 0, 0, 7)
  5389	
  5390		case AFMINNMD:
  5391			return FPOP2S(0, 0, 1, 7)
  5392	
  5393		case AFNMULS:
  5394			return FPOP2S(0, 0, 0, 8)
  5395	
  5396		case AFNMULD:
  5397			return FPOP2S(0, 0, 1, 8)
  5398	
  5399		case AFCMPS:
  5400			return FPCMP(0, 0, 0, 0, 0)
  5401	
  5402		case AFCMPD:
  5403			return FPCMP(0, 0, 1, 0, 0)
  5404	
  5405		case AFCMPES:
  5406			return FPCMP(0, 0, 0, 0, 16)
  5407	
  5408		case AFCMPED:
  5409			return FPCMP(0, 0, 1, 0, 16)
  5410	
  5411		case AFCCMPS:
  5412			return FPCCMP(0, 0, 0, 0)
  5413	
  5414		case AFCCMPD:
  5415			return FPCCMP(0, 0, 1, 0)
  5416	
  5417		case AFCCMPES:
  5418			return FPCCMP(0, 0, 0, 1)
  5419	
  5420		case AFCCMPED:
  5421			return FPCCMP(0, 0, 1, 1)
  5422	
  5423		case AFCSELS:
  5424			return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
  5425	
  5426		case AFCSELD:
  5427			return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
  5428	
  5429		case AFMOVS:
  5430			return FPOP1S(0, 0, 0, 0)
  5431	
  5432		case AFABSS:
  5433			return FPOP1S(0, 0, 0, 1)
  5434	
  5435		case AFNEGS:
  5436			return FPOP1S(0, 0, 0, 2)
  5437	
  5438		case AFSQRTS:
  5439			return FPOP1S(0, 0, 0, 3)
  5440	
  5441		case AFCVTSD:
  5442			return FPOP1S(0, 0, 0, 5)
  5443	
  5444		case AFCVTSH:
  5445			return FPOP1S(0, 0, 0, 7)
  5446	
  5447		case AFRINTNS:
  5448			return FPOP1S(0, 0, 0, 8)
  5449	
  5450		case AFRINTPS:
  5451			return FPOP1S(0, 0, 0, 9)
  5452	
  5453		case AFRINTMS:
  5454			return FPOP1S(0, 0, 0, 10)
  5455	
  5456		case AFRINTZS:
  5457			return FPOP1S(0, 0, 0, 11)
  5458	
  5459		case AFRINTAS:
  5460			return FPOP1S(0, 0, 0, 12)
  5461	
  5462		case AFRINTXS:
  5463			return FPOP1S(0, 0, 0, 14)
  5464	
  5465		case AFRINTIS:
  5466			return FPOP1S(0, 0, 0, 15)
  5467	
  5468		case AFMOVD:
  5469			return FPOP1S(0, 0, 1, 0)
  5470	
  5471		case AFABSD:
  5472			return FPOP1S(0, 0, 1, 1)
  5473	
  5474		case AFNEGD:
  5475			return FPOP1S(0, 0, 1, 2)
  5476	
  5477		case AFSQRTD:
  5478			return FPOP1S(0, 0, 1, 3)
  5479	
  5480		case AFCVTDS:
  5481			return FPOP1S(0, 0, 1, 4)
  5482	
  5483		case AFCVTDH:
  5484			return FPOP1S(0, 0, 1, 7)
  5485	
  5486		case AFRINTND:
  5487			return FPOP1S(0, 0, 1, 8)
  5488	
  5489		case AFRINTPD:
  5490			return FPOP1S(0, 0, 1, 9)
  5491	
  5492		case AFRINTMD:
  5493			return FPOP1S(0, 0, 1, 10)
  5494	
  5495		case AFRINTZD:
  5496			return FPOP1S(0, 0, 1, 11)
  5497	
  5498		case AFRINTAD:
  5499			return FPOP1S(0, 0, 1, 12)
  5500	
  5501		case AFRINTXD:
  5502			return FPOP1S(0, 0, 1, 14)
  5503	
  5504		case AFRINTID:
  5505			return FPOP1S(0, 0, 1, 15)
  5506	
  5507		case AFCVTHS:
  5508			return FPOP1S(0, 0, 3, 4)
  5509	
  5510		case AFCVTHD:
  5511			return FPOP1S(0, 0, 3, 5)
  5512	
  5513		case AVADD:
  5514			return 7<<25 | 1<<21 | 1<<15 | 1<<10
  5515	
  5516		case AVADDP:
  5517			return 7<<25 | 1<<21 | 1<<15 | 15<<10
  5518	
  5519		case AVAND:
  5520			return 7<<25 | 1<<21 | 7<<10
  5521	
  5522		case AVCMEQ:
  5523			return 1<<29 | 0x71<<21 | 0x23<<10
  5524	
  5525		case AVCNT:
  5526			return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
  5527	
  5528		case AVZIP1:
  5529			return 0xE<<24 | 3<<12 | 2<<10
  5530	
  5531		case AVZIP2:
  5532			return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
  5533	
  5534		case AVEOR:
  5535			return 1<<29 | 0x71<<21 | 7<<10
  5536	
  5537		case AVORR:
  5538			return 7<<25 | 5<<21 | 7<<10
  5539	
  5540		case AVREV32:
  5541			return 11<<26 | 2<<24 | 1<<21 | 1<<11
  5542	
  5543		case AVREV64:
  5544			return 3<<26 | 2<<24 | 1<<21 | 1<<11
  5545	
  5546		case AVMOV:
  5547			return 7<<25 | 5<<21 | 7<<10
  5548	
  5549		case AVADDV:
  5550			return 7<<25 | 3<<20 | 3<<15 | 7<<11
  5551	
  5552		case AVUADDLV:
  5553			return 1<<29 | 7<<25 | 3<<20 | 7<<11
  5554	
  5555		case AVFMLA:
  5556			return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
  5557	
  5558		case AVFMLS:
  5559			return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
  5560	
  5561		case AVPMULL, AVPMULL2:
  5562			return 0xE<<24 | 1<<21 | 0x38<<10
  5563	
  5564		case AVRBIT:
  5565			return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
  5566		}
  5567	
  5568		c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
  5569		return 0
  5570	}
  5571	
  5572	/*
  5573	 * imm -> Rd
  5574	 * imm op Rn -> Rd
  5575	 */
  5576	func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
  5577		switch a {
  5578		/* op $addcon, Rn, Rd */
  5579		case AMOVD, AADD:
  5580			return S64 | 0<<30 | 0<<29 | 0x11<<24
  5581	
  5582		case ACMN, AADDS:
  5583			return S64 | 0<<30 | 1<<29 | 0x11<<24
  5584	
  5585		case AMOVW, AADDW:
  5586			return S32 | 0<<30 | 0<<29 | 0x11<<24
  5587	
  5588		case ACMNW, AADDSW:
  5589			return S32 | 0<<30 | 1<<29 | 0x11<<24
  5590	
  5591		case ASUB:
  5592			return S64 | 1<<30 | 0<<29 | 0x11<<24
  5593	
  5594		case ACMP, ASUBS:
  5595			return S64 | 1<<30 | 1<<29 | 0x11<<24
  5596	
  5597		case ASUBW:
  5598			return S32 | 1<<30 | 0<<29 | 0x11<<24
  5599	
  5600		case ACMPW, ASUBSW:
  5601			return S32 | 1<<30 | 1<<29 | 0x11<<24
  5602	
  5603			/* op $imm(SB), Rd; op label, Rd */
  5604		case AADR:
  5605			return 0<<31 | 0x10<<24
  5606	
  5607		case AADRP:
  5608			return 1<<31 | 0x10<<24
  5609	
  5610			/* op $bimm, Rn, Rd */
  5611		case AAND, ABIC:
  5612			return S64 | 0<<29 | 0x24<<23
  5613	
  5614		case AANDW, ABICW:
  5615			return S32 | 0<<29 | 0x24<<23 | 0<<22
  5616	
  5617		case AORR, AORN:
  5618			return S64 | 1<<29 | 0x24<<23
  5619	
  5620		case AORRW, AORNW:
  5621			return S32 | 1<<29 | 0x24<<23 | 0<<22
  5622	
  5623		case AEOR, AEON:
  5624			return S64 | 2<<29 | 0x24<<23
  5625	
  5626		case AEORW, AEONW:
  5627			return S32 | 2<<29 | 0x24<<23 | 0<<22
  5628	
  5629		case AANDS, ABICS, ATST:
  5630			return S64 | 3<<29 | 0x24<<23
  5631	
  5632		case AANDSW, ABICSW, ATSTW:
  5633			return S32 | 3<<29 | 0x24<<23 | 0<<22
  5634	
  5635		case AASR:
  5636			return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
  5637	
  5638		case AASRW:
  5639			return S32 | 0<<29 | 0x26<<23 | 0<<22
  5640	
  5641			/* op $width, $lsb, Rn, Rd */
  5642		case ABFI:
  5643			return S64 | 2<<29 | 0x26<<23 | 1<<22
  5644			/* alias of BFM */
  5645	
  5646		case ABFIW:
  5647			return S32 | 2<<29 | 0x26<<23 | 0<<22
  5648	
  5649			/* op $imms, $immr, Rn, Rd */
  5650		case ABFM:
  5651			return S64 | 1<<29 | 0x26<<23 | 1<<22
  5652	
  5653		case ABFMW:
  5654			return S32 | 1<<29 | 0x26<<23 | 0<<22
  5655	
  5656		case ASBFM:
  5657			return S64 | 0<<29 | 0x26<<23 | 1<<22
  5658	
  5659		case ASBFMW:
  5660			return S32 | 0<<29 | 0x26<<23 | 0<<22
  5661	
  5662		case AUBFM:
  5663			return S64 | 2<<29 | 0x26<<23 | 1<<22
  5664	
  5665		case AUBFMW:
  5666			return S32 | 2<<29 | 0x26<<23 | 0<<22
  5667	
  5668		case ABFXIL:
  5669			return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
  5670	
  5671		case ABFXILW:
  5672			return S32 | 1<<29 | 0x26<<23 | 0<<22
  5673	
  5674		case AEXTR:
  5675			return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
  5676	
  5677		case AEXTRW:
  5678			return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
  5679	
  5680		case ACBNZ:
  5681			return S64 | 0x1A<<25 | 1<<24
  5682	
  5683		case ACBNZW:
  5684			return S32 | 0x1A<<25 | 1<<24
  5685	
  5686		case ACBZ:
  5687			return S64 | 0x1A<<25 | 0<<24
  5688	
  5689		case ACBZW:
  5690			return S32 | 0x1A<<25 | 0<<24
  5691	
  5692		case ACCMN:
  5693			return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5694	
  5695		case ACCMNW:
  5696			return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  5697	
  5698		case ACCMP:
  5699			return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5700	
  5701		case ACCMPW:
  5702			return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  5703	
  5704		case AMOVK:
  5705			return S64 | 3<<29 | 0x25<<23
  5706	
  5707		case AMOVKW:
  5708			return S32 | 3<<29 | 0x25<<23
  5709	
  5710		case AMOVN:
  5711			return S64 | 0<<29 | 0x25<<23
  5712	
  5713		case AMOVNW:
  5714			return S32 | 0<<29 | 0x25<<23
  5715	
  5716		case AMOVZ:
  5717			return S64 | 2<<29 | 0x25<<23
  5718	
  5719		case AMOVZW:
  5720			return S32 | 2<<29 | 0x25<<23
  5721	
  5722		case AMSR:
  5723			return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
  5724	
  5725		case AAT,
  5726			ADC,
  5727			AIC,
  5728			ATLBI,
  5729			ASYS:
  5730			return SYSOP(0, 1, 0, 0, 0, 0, 0)
  5731	
  5732		case ASYSL:
  5733			return SYSOP(1, 1, 0, 0, 0, 0, 0)
  5734	
  5735		case ATBZ:
  5736			return 0x36 << 24
  5737	
  5738		case ATBNZ:
  5739			return 0x37 << 24
  5740	
  5741		case ADSB:
  5742			return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
  5743	
  5744		case ADMB:
  5745			return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
  5746	
  5747		case AISB:
  5748			return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
  5749	
  5750		case AHINT:
  5751			return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
  5752	
  5753		case AVEXT:
  5754			return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
  5755	
  5756		case AVUSHR:
  5757			return 0x5E<<23 | 1<<10
  5758	
  5759		case AVSHL:
  5760			return 0x1E<<23 | 21<<10
  5761	
  5762		case AVSRI:
  5763			return 0x5E<<23 | 17<<10
  5764		}
  5765	
  5766		c.ctxt.Diag("%v: bad irr %v", p, a)
  5767		return 0
  5768	}
  5769	
  5770	func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
  5771		switch a {
  5772		case ACLS:
  5773			return S64 | OPBIT(5)
  5774	
  5775		case ACLSW:
  5776			return S32 | OPBIT(5)
  5777	
  5778		case ACLZ:
  5779			return S64 | OPBIT(4)
  5780	
  5781		case ACLZW:
  5782			return S32 | OPBIT(4)
  5783	
  5784		case ARBIT:
  5785			return S64 | OPBIT(0)
  5786	
  5787		case ARBITW:
  5788			return S32 | OPBIT(0)
  5789	
  5790		case AREV:
  5791			return S64 | OPBIT(3)
  5792	
  5793		case AREVW:
  5794			return S32 | OPBIT(2)
  5795	
  5796		case AREV16:
  5797			return S64 | OPBIT(1)
  5798	
  5799		case AREV16W:
  5800			return S32 | OPBIT(1)
  5801	
  5802		case AREV32:
  5803			return S64 | OPBIT(2)
  5804	
  5805		default:
  5806			c.ctxt.Diag("bad bit op\n%v", p)
  5807			return 0
  5808		}
  5809	}
  5810	
  5811	/*
  5812	 * add/subtract sign or zero-extended register
  5813	 */
  5814	func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
  5815		extension := uint32(0)
  5816		if !extend {
  5817			switch a {
  5818			case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
  5819				extension = LSL0_64
  5820	
  5821			case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
  5822				extension = LSL0_32
  5823			}
  5824		}
  5825	
  5826		switch a {
  5827		case AADD:
  5828			return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5829	
  5830		case AADDW:
  5831			return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5832	
  5833		case ACMN, AADDS:
  5834			return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5835	
  5836		case ACMNW, AADDSW:
  5837			return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5838	
  5839		case ASUB:
  5840			return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5841	
  5842		case ASUBW:
  5843			return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5844	
  5845		case ACMP, ASUBS:
  5846			return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5847	
  5848		case ACMPW, ASUBSW:
  5849			return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5850		}
  5851	
  5852		c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
  5853		return 0
  5854	}
  5855	
  5856	func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
  5857		switch a {
  5858		case ASVC:
  5859			return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
  5860	
  5861		case AHVC:
  5862			return 0xD4<<24 | 0<<21 | 2
  5863	
  5864		case ASMC:
  5865			return 0xD4<<24 | 0<<21 | 3
  5866	
  5867		case ABRK:
  5868			return 0xD4<<24 | 1<<21 | 0
  5869	
  5870		case AHLT:
  5871			return 0xD4<<24 | 2<<21 | 0
  5872	
  5873		case ADCPS1:
  5874			return 0xD4<<24 | 5<<21 | 1
  5875	
  5876		case ADCPS2:
  5877			return 0xD4<<24 | 5<<21 | 2
  5878	
  5879		case ADCPS3:
  5880			return 0xD4<<24 | 5<<21 | 3
  5881	
  5882		case ACLREX:
  5883			return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
  5884		}
  5885	
  5886		c.ctxt.Diag("%v: bad imm %v", p, a)
  5887		return 0
  5888	}
  5889	
  5890	func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
  5891		v := int64(0)
  5892		t := int64(0)
  5893		if p.Pcond != nil {
  5894			v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
  5895			if (v & ((1 << uint(shift)) - 1)) != 0 {
  5896				c.ctxt.Diag("misaligned label\n%v", p)
  5897			}
  5898			v >>= uint(shift)
  5899			t = int64(1) << uint(flen-1)
  5900			if v < -t || v >= t {
  5901				c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond)
  5902				panic("branch too far")
  5903			}
  5904		}
  5905	
  5906		return v & ((t << 1) - 1)
  5907	}
  5908	
  5909	/*
  5910	 * pc-relative branches
  5911	 */
  5912	func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
  5913		switch a {
  5914		case ABEQ:
  5915			return OPBcc(0x0)
  5916	
  5917		case ABNE:
  5918			return OPBcc(0x1)
  5919	
  5920		case ABCS:
  5921			return OPBcc(0x2)
  5922	
  5923		case ABHS:
  5924			return OPBcc(0x2)
  5925	
  5926		case ABCC:
  5927			return OPBcc(0x3)
  5928	
  5929		case ABLO:
  5930			return OPBcc(0x3)
  5931	
  5932		case ABMI:
  5933			return OPBcc(0x4)
  5934	
  5935		case ABPL:
  5936			return OPBcc(0x5)
  5937	
  5938		case ABVS:
  5939			return OPBcc(0x6)
  5940	
  5941		case ABVC:
  5942			return OPBcc(0x7)
  5943	
  5944		case ABHI:
  5945			return OPBcc(0x8)
  5946	
  5947		case ABLS:
  5948			return OPBcc(0x9)
  5949	
  5950		case ABGE:
  5951			return OPBcc(0xa)
  5952	
  5953		case ABLT:
  5954			return OPBcc(0xb)
  5955	
  5956		case ABGT:
  5957			return OPBcc(0xc)
  5958	
  5959		case ABLE:
  5960			return OPBcc(0xd) /* imm19<<5 | cond */
  5961	
  5962		case AB:
  5963			return 0<<31 | 5<<26 /* imm26 */
  5964	
  5965		case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
  5966			return 1<<31 | 5<<26
  5967		}
  5968	
  5969		c.ctxt.Diag("%v: bad bra %v", p, a)
  5970		return 0
  5971	}
  5972	
  5973	func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
  5974		switch a {
  5975		case ABL:
  5976			return OPBLR(1) /* BLR */
  5977	
  5978		case AB:
  5979			return OPBLR(0) /* BR */
  5980	
  5981		case obj.ARET:
  5982			return OPBLR(2) /* RET */
  5983		}
  5984	
  5985		c.ctxt.Diag("%v: bad brr %v", p, a)
  5986		return 0
  5987	}
  5988	
  5989	func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
  5990		switch a {
  5991		case ADRPS:
  5992			return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
  5993	
  5994		case AERET:
  5995			return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
  5996	
  5997		// case ANOP:
  5998		// 	return SYSHINT(0)
  5999	
  6000		case AYIELD:
  6001			return SYSHINT(1)
  6002	
  6003		case AWFE:
  6004			return SYSHINT(2)
  6005	
  6006		case AWFI:
  6007			return SYSHINT(3)
  6008	
  6009		case ASEV:
  6010			return SYSHINT(4)
  6011	
  6012		case ASEVL:
  6013			return SYSHINT(5)
  6014		}
  6015	
  6016		c.ctxt.Diag("%v: bad op0 %v", p, a)
  6017		return 0
  6018	}
  6019	
  6020	/*
  6021	 * register offset
  6022	 */
  6023	func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
  6024		switch a {
  6025		case ALDAR:
  6026			return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
  6027	
  6028		case ALDARW:
  6029			return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
  6030	
  6031		case ALDARB:
  6032			return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
  6033	
  6034		case ALDARH:
  6035			return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
  6036	
  6037		case ALDAXP:
  6038			return LDSTX(3, 0, 1, 1, 1)
  6039	
  6040		case ALDAXPW:
  6041			return LDSTX(2, 0, 1, 1, 1)
  6042	
  6043		case ALDAXR:
  6044			return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
  6045	
  6046		case ALDAXRW:
  6047			return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
  6048	
  6049		case ALDAXRB:
  6050			return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
  6051	
  6052		case ALDAXRH:
  6053			return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
  6054	
  6055		case ALDXR:
  6056			return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
  6057	
  6058		case ALDXRB:
  6059			return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
  6060	
  6061		case ALDXRH:
  6062			return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
  6063	
  6064		case ALDXRW:
  6065			return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
  6066	
  6067		case ALDXP:
  6068			return LDSTX(3, 0, 1, 1, 0)
  6069	
  6070		case ALDXPW:
  6071			return LDSTX(2, 0, 1, 1, 0)
  6072	
  6073		case AMOVNP:
  6074			return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6075	
  6076		case AMOVNPW:
  6077			return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6078		}
  6079	
  6080		c.ctxt.Diag("bad opload %v\n%v", a, p)
  6081		return 0
  6082	}
  6083	
  6084	func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
  6085		switch a {
  6086		case ASTLR:
  6087			return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
  6088	
  6089		case ASTLRB:
  6090			return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
  6091	
  6092		case ASTLRH:
  6093			return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
  6094	
  6095		case ASTLP:
  6096			return LDSTX(3, 0, 0, 1, 1)
  6097	
  6098		case ASTLPW:
  6099			return LDSTX(2, 0, 0, 1, 1)
  6100	
  6101		case ASTLRW:
  6102			return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
  6103	
  6104		case ASTLXP:
  6105			return LDSTX(3, 0, 0, 1, 1)
  6106	
  6107		case ASTLXPW:
  6108			return LDSTX(2, 0, 0, 1, 1)
  6109	
  6110		case ASTLXR:
  6111			return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
  6112	
  6113		case ASTLXRB:
  6114			return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
  6115	
  6116		case ASTLXRH:
  6117			return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
  6118	
  6119		case ASTLXRW:
  6120			return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
  6121	
  6122		case ASTXR:
  6123			return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
  6124	
  6125		case ASTXRB:
  6126			return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
  6127	
  6128		case ASTXRH:
  6129			return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
  6130	
  6131		case ASTXP:
  6132			return LDSTX(3, 0, 0, 1, 0)
  6133	
  6134		case ASTXPW:
  6135			return LDSTX(2, 0, 0, 1, 0)
  6136	
  6137		case ASTXRW:
  6138			return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
  6139	
  6140		case AMOVNP:
  6141			return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6142	
  6143		case AMOVNPW:
  6144			return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6145		}
  6146	
  6147		c.ctxt.Diag("bad opstore %v\n%v", a, p)
  6148		return 0
  6149	}
  6150	
  6151	/*
  6152	 * load/store register (unsigned immediate) C3.3.13
  6153	 *	these produce 64-bit values (when there's an option)
  6154	 */
  6155	func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  6156		if v < 0 || v >= (1<<12) {
  6157			c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  6158		}
  6159		o |= (v & 0xFFF) << 10
  6160		o |= int32(b&31) << 5
  6161		o |= int32(r & 31)
  6162		return uint32(o)
  6163	}
  6164	
  6165	func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
  6166		switch a {
  6167		case AMOVD:
  6168			return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
  6169	
  6170		case AMOVW:
  6171			return LDSTR12U(2, 0, 2)
  6172	
  6173		case AMOVWU:
  6174			return LDSTR12U(2, 0, 1)
  6175	
  6176		case AMOVH:
  6177			return LDSTR12U(1, 0, 2)
  6178	
  6179		case AMOVHU:
  6180			return LDSTR12U(1, 0, 1)
  6181	
  6182		case AMOVB:
  6183			return LDSTR12U(0, 0, 2)
  6184	
  6185		case AMOVBU:
  6186			return LDSTR12U(0, 0, 1)
  6187	
  6188		case AFMOVS:
  6189			return LDSTR12U(2, 1, 1)
  6190	
  6191		case AFMOVD:
  6192			return LDSTR12U(3, 1, 1)
  6193		}
  6194	
  6195		c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
  6196		return 0
  6197	}
  6198	
  6199	func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
  6200		return LD2STR(c.opldr12(p, a))
  6201	}
  6202	
  6203	/*
  6204	 * load/store register (unscaled immediate) C3.3.12
  6205	 */
  6206	func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  6207		if v < -256 || v > 255 {
  6208			c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  6209		}
  6210		o |= (v & 0x1FF) << 12
  6211		o |= int32(b&31) << 5
  6212		o |= int32(r & 31)
  6213		return uint32(o)
  6214	}
  6215	
  6216	func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
  6217		switch a {
  6218		case AMOVD:
  6219			return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
  6220	
  6221		case AMOVW:
  6222			return LDSTR9S(2, 0, 2)
  6223	
  6224		case AMOVWU:
  6225			return LDSTR9S(2, 0, 1)
  6226	
  6227		case AMOVH:
  6228			return LDSTR9S(1, 0, 2)
  6229	
  6230		case AMOVHU:
  6231			return LDSTR9S(1, 0, 1)
  6232	
  6233		case AMOVB:
  6234			return LDSTR9S(0, 0, 2)
  6235	
  6236		case AMOVBU:
  6237			return LDSTR9S(0, 0, 1)
  6238	
  6239		case AFMOVS:
  6240			return LDSTR9S(2, 1, 1)
  6241	
  6242		case AFMOVD:
  6243			return LDSTR9S(3, 1, 1)
  6244		}
  6245	
  6246		c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
  6247		return 0
  6248	}
  6249	
  6250	func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
  6251		return LD2STR(c.opldr9(p, a))
  6252	}
  6253	
  6254	func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
  6255		switch a {
  6256		case AMOVD:
  6257			return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
  6258	
  6259		case AMOVW:
  6260			return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  6261	
  6262		case AMOVWU:
  6263			return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  6264	
  6265		case AMOVH:
  6266			return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  6267	
  6268		case AMOVHU:
  6269			return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  6270	
  6271		case AMOVB:
  6272			return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  6273	
  6274		case AMOVBU:
  6275			return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  6276	
  6277		case AFMOVS:
  6278			return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
  6279	
  6280		case AFMOVD:
  6281			return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
  6282	
  6283		case APRFM:
  6284			return 0xf9<<24 | 2<<22
  6285	
  6286		}
  6287	
  6288		c.ctxt.Diag("bad opldr %v\n%v", a, p)
  6289		return 0
  6290	}
  6291	
  6292	// olsxrr attaches register operands to a load/store opcode supplied in o.
  6293	// The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
  6294	func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
  6295		o |= int32(r1&31) << 5
  6296		o |= int32(r2&31) << 16
  6297		o |= int32(r & 31)
  6298		return uint32(o)
  6299	}
  6300	
  6301	// opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  6302	// for load instruction with register offset.
  6303	// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  6304	func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  6305		OptionS := uint32(0x1a)
  6306		if extension {
  6307			OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
  6308		}
  6309		switch a {
  6310		case AMOVD:
  6311			return OptionS<<10 | 0x3<<21 | 0x1f<<27
  6312		case AMOVW:
  6313			return OptionS<<10 | 0x5<<21 | 0x17<<27
  6314		case AMOVWU:
  6315			return OptionS<<10 | 0x3<<21 | 0x17<<27
  6316		case AMOVH:
  6317			return OptionS<<10 | 0x5<<21 | 0x0f<<27
  6318		case AMOVHU:
  6319			return OptionS<<10 | 0x3<<21 | 0x0f<<27
  6320		case AMOVB:
  6321			return OptionS<<10 | 0x5<<21 | 0x07<<27
  6322		case AMOVBU:
  6323			return OptionS<<10 | 0x3<<21 | 0x07<<27
  6324		case AFMOVS:
  6325			return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
  6326		case AFMOVD:
  6327			return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
  6328		}
  6329		c.ctxt.Diag("bad opldrr %v\n%v", a, p)
  6330		return 0
  6331	}
  6332	
  6333	// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  6334	// for store instruction with register offset.
  6335	// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  6336	func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  6337		OptionS := uint32(0x1a)
  6338		if extension {
  6339			OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
  6340		}
  6341		switch a {
  6342		case AMOVD:
  6343			return OptionS<<10 | 0x1<<21 | 0x1f<<27
  6344		case AMOVW, AMOVWU:
  6345			return OptionS<<10 | 0x1<<21 | 0x17<<27
  6346		case AMOVH, AMOVHU:
  6347			return OptionS<<10 | 0x1<<21 | 0x0f<<27
  6348		case AMOVB, AMOVBU:
  6349			return OptionS<<10 | 0x1<<21 | 0x07<<27
  6350		case AFMOVS:
  6351			return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
  6352		case AFMOVD:
  6353			return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
  6354		}
  6355		c.ctxt.Diag("bad opstrr %v\n%v", a, p)
  6356		return 0
  6357	}
  6358	
  6359	func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
  6360		if (v & 0xFFF000) != 0 {
  6361			if v&0xFFF != 0 {
  6362				c.ctxt.Diag("%v misuses oaddi", p)
  6363			}
  6364			v >>= 12
  6365			o1 |= 1 << 22
  6366		}
  6367	
  6368		o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
  6369		return uint32(o1)
  6370	}
  6371	
  6372	/*
  6373	 * load a literal value into dr
  6374	 */
  6375	func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
  6376		var o1 int32
  6377		if p.Pcond == nil { /* not in literal pool */
  6378			c.aclass(a)
  6379			c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
  6380	
  6381			/* TODO: could be clever, and use general constant builder */
  6382			o1 = int32(c.opirr(p, AADD))
  6383	
  6384			v := int32(c.instoffset)
  6385			if v != 0 && (v&0xFFF) == 0 {
  6386				v >>= 12
  6387				o1 |= 1 << 22 /* shift, by 12 */
  6388			}
  6389	
  6390			o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
  6391		} else {
  6392			fp, w := 0, 0
  6393			switch as {
  6394			case AFMOVS:
  6395				fp = 1
  6396				w = 0 /* 32-bit SIMD/FP */
  6397	
  6398			case AFMOVD:
  6399				fp = 1
  6400				w = 1 /* 64-bit SIMD/FP */
  6401	
  6402			case AMOVD:
  6403				if p.Pcond.As == ADWORD {
  6404					w = 1 /* 64-bit */
  6405				} else if p.Pcond.To.Offset < 0 {
  6406					w = 2 /* 32-bit, sign-extended to 64-bit */
  6407				} else if p.Pcond.To.Offset >= 0 {
  6408					w = 0 /* 32-bit, zero-extended to 64-bit */
  6409				} else {
  6410					c.ctxt.Diag("invalid operand %v in %v", a, p)
  6411				}
  6412	
  6413			case AMOVBU, AMOVHU, AMOVWU:
  6414				w = 0 /* 32-bit, zero-extended to 64-bit */
  6415	
  6416			case AMOVB, AMOVH, AMOVW:
  6417				w = 2 /* 32-bit, sign-extended to 64-bit */
  6418	
  6419			default:
  6420				c.ctxt.Diag("invalid operation %v in %v", as, p)
  6421			}
  6422	
  6423			v := int32(c.brdist(p, 0, 19, 2))
  6424			o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
  6425			o1 |= (v & 0x7FFFF) << 5
  6426			o1 |= int32(dr & 31)
  6427		}
  6428	
  6429		return uint32(o1)
  6430	}
  6431	
  6432	// load a constant (MOVCON or BITCON) in a into rt
  6433	func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
  6434		if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
  6435			// or $bitcon, REGZERO, rt
  6436			mode := 64
  6437			var as1 obj.As
  6438			switch as {
  6439			case AMOVW:
  6440				as1 = AORRW
  6441				mode = 32
  6442			case AMOVD:
  6443				as1 = AORR
  6444			}
  6445			o1 = c.opirr(p, as1)
  6446			o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  6447			return o1
  6448		}
  6449	
  6450		if as == AMOVW {
  6451			d := uint32(a.Offset)
  6452			s := movcon(int64(d))
  6453			if s < 0 || 16*s >= 32 {
  6454				d = ^d
  6455				s = movcon(int64(d))
  6456				if s < 0 || 16*s >= 32 {
  6457					c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
  6458				}
  6459				o1 = c.opirr(p, AMOVNW)
  6460			} else {
  6461				o1 = c.opirr(p, AMOVZW)
  6462			}
  6463			o1 |= MOVCONST(int64(d), s, rt)
  6464		}
  6465		if as == AMOVD {
  6466			d := a.Offset
  6467			s := movcon(d)
  6468			if s < 0 || 16*s >= 64 {
  6469				d = ^d
  6470				s = movcon(d)
  6471				if s < 0 || 16*s >= 64 {
  6472					c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
  6473				}
  6474				o1 = c.opirr(p, AMOVN)
  6475			} else {
  6476				o1 = c.opirr(p, AMOVZ)
  6477			}
  6478			o1 |= MOVCONST(d, s, rt)
  6479		}
  6480		return o1
  6481	}
  6482	
  6483	// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
  6484	// put the instruction sequence in os and return the number of instructions.
  6485	func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
  6486		switch as {
  6487		case AMOVW:
  6488			d := uint32(a.Offset)
  6489			// use MOVZW and MOVKW to load a constant to rt
  6490			os[0] = c.opirr(p, AMOVZW)
  6491			os[0] |= MOVCONST(int64(d), 0, rt)
  6492			os[1] = c.opirr(p, AMOVKW)
  6493			os[1] |= MOVCONST(int64(d), 1, rt)
  6494			return 2
  6495	
  6496		case AMOVD:
  6497			d := a.Offset
  6498			dn := ^d
  6499			var immh [4]uint64
  6500			var i int
  6501			zeroCount := int(0)
  6502			negCount := int(0)
  6503			for i = 0; i < 4; i++ {
  6504				immh[i] = uint64((d >> uint(i*16)) & 0xffff)
  6505				if immh[i] == 0 {
  6506					zeroCount++
  6507				} else if immh[i] == 0xffff {
  6508					negCount++
  6509				}
  6510			}
  6511	
  6512			if zeroCount == 4 || negCount == 4 {
  6513				c.ctxt.Diag("the immediate should be MOVCON: %v", p)
  6514			}
  6515			switch {
  6516			case zeroCount == 3:
  6517				// one MOVZ
  6518				for i = 0; i < 4; i++ {
  6519					if immh[i] != 0 {
  6520						os[0] = c.opirr(p, AMOVZ)
  6521						os[0] |= MOVCONST(d, i, rt)
  6522						break
  6523					}
  6524				}
  6525				return 1
  6526	
  6527			case negCount == 3:
  6528				// one MOVN
  6529				for i = 0; i < 4; i++ {
  6530					if immh[i] != 0xffff {
  6531						os[0] = c.opirr(p, AMOVN)
  6532						os[0] |= MOVCONST(dn, i, rt)
  6533						break
  6534					}
  6535				}
  6536				return 1
  6537	
  6538			case zeroCount == 2:
  6539				// one MOVZ and one MOVK
  6540				for i = 0; i < 4; i++ {
  6541					if immh[i] != 0 {
  6542						os[0] = c.opirr(p, AMOVZ)
  6543						os[0] |= MOVCONST(d, i, rt)
  6544						i++
  6545						break
  6546					}
  6547				}
  6548				for ; i < 4; i++ {
  6549					if immh[i] != 0 {
  6550						os[1] = c.opirr(p, AMOVK)
  6551						os[1] |= MOVCONST(d, i, rt)
  6552					}
  6553				}
  6554				return 2
  6555	
  6556			case negCount == 2:
  6557				// one MOVN and one MOVK
  6558				for i = 0; i < 4; i++ {
  6559					if immh[i] != 0xffff {
  6560						os[0] = c.opirr(p, AMOVN)
  6561						os[0] |= MOVCONST(dn, i, rt)
  6562						i++
  6563						break
  6564					}
  6565				}
  6566				for ; i < 4; i++ {
  6567					if immh[i] != 0xffff {
  6568						os[1] = c.opirr(p, AMOVK)
  6569						os[1] |= MOVCONST(d, i, rt)
  6570					}
  6571				}
  6572				return 2
  6573	
  6574			case zeroCount == 1:
  6575				// one MOVZ and two MOVKs
  6576				for i = 0; i < 4; i++ {
  6577					if immh[i] != 0 {
  6578						os[0] = c.opirr(p, AMOVZ)
  6579						os[0] |= MOVCONST(d, i, rt)
  6580						i++
  6581						break
  6582					}
  6583				}
  6584	
  6585				for j := 1; i < 4; i++ {
  6586					if immh[i] != 0 {
  6587						os[j] = c.opirr(p, AMOVK)
  6588						os[j] |= MOVCONST(d, i, rt)
  6589						j++
  6590					}
  6591				}
  6592				return 3
  6593	
  6594			case negCount == 1:
  6595				// one MOVN and two MOVKs
  6596				for i = 0; i < 4; i++ {
  6597					if immh[i] != 0xffff {
  6598						os[0] = c.opirr(p, AMOVN)
  6599						os[0] |= MOVCONST(dn, i, rt)
  6600						i++
  6601						break
  6602					}
  6603				}
  6604	
  6605				for j := 1; i < 4; i++ {
  6606					if immh[i] != 0xffff {
  6607						os[j] = c.opirr(p, AMOVK)
  6608						os[j] |= MOVCONST(d, i, rt)
  6609						j++
  6610					}
  6611				}
  6612				return 3
  6613	
  6614			default:
  6615				// one MOVZ and 3 MOVKs
  6616				os[0] = c.opirr(p, AMOVZ)
  6617				os[0] |= MOVCONST(d, 0, rt)
  6618				for i = 1; i < 4; i++ {
  6619					os[i] = c.opirr(p, AMOVK)
  6620					os[i] |= MOVCONST(d, i, rt)
  6621				}
  6622				return 4
  6623			}
  6624		default:
  6625			return 0
  6626		}
  6627	}
  6628	
  6629	func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
  6630		var b uint32
  6631		o := c.opirr(p, a)
  6632		if (o & (1 << 31)) == 0 {
  6633			b = 32
  6634		} else {
  6635			b = 64
  6636		}
  6637		if r < 0 || uint32(r) >= b {
  6638			c.ctxt.Diag("illegal bit number\n%v", p)
  6639		}
  6640		o |= (uint32(r) & 0x3F) << 16
  6641		if s < 0 || uint32(s) >= b {
  6642			c.ctxt.Diag("illegal bit number\n%v", p)
  6643		}
  6644		o |= (uint32(s) & 0x3F) << 10
  6645		o |= (uint32(rf&31) << 5) | uint32(rt&31)
  6646		return o
  6647	}
  6648	
  6649	func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
  6650		var b uint32
  6651		o := c.opirr(p, a)
  6652		if (o & (1 << 31)) != 0 {
  6653			b = 63
  6654		} else {
  6655			b = 31
  6656		}
  6657		if v < 0 || uint32(v) > b {
  6658			c.ctxt.Diag("illegal bit number\n%v", p)
  6659		}
  6660		o |= uint32(v) << 10
  6661		o |= uint32(rn&31) << 5
  6662		o |= uint32(rm&31) << 16
  6663		o |= uint32(rt & 31)
  6664		return o
  6665	}
  6666	
  6667	/* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
  6668	func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
  6669		wback := false
  6670		if o.scond == C_XPOST || o.scond == C_XPRE {
  6671			wback = true
  6672		}
  6673		switch p.As {
  6674		case ALDP, ALDPW, ALDPSW:
  6675			c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  6676		case ASTP, ASTPW:
  6677			if wback == true {
  6678				c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
  6679			}
  6680		case AFLDPD, AFLDPS:
  6681			c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  6682		}
  6683		var ret uint32
  6684		// check offset
  6685		switch p.As {
  6686		case AFLDPD, AFSTPD:
  6687			if vo < -512 || vo > 504 || vo%8 != 0 {
  6688				c.ctxt.Diag("invalid offset %v\n", p)
  6689			}
  6690			vo /= 8
  6691			ret = 1<<30 | 1<<26
  6692		case ALDP, ASTP:
  6693			if vo < -512 || vo > 504 || vo%8 != 0 {
  6694				c.ctxt.Diag("invalid offset %v\n", p)
  6695			}
  6696			vo /= 8
  6697			ret = 2 << 30
  6698		case AFLDPS, AFSTPS:
  6699			if vo < -256 || vo > 252 || vo%4 != 0 {
  6700				c.ctxt.Diag("invalid offset %v\n", p)
  6701			}
  6702			vo /= 4
  6703			ret = 1 << 26
  6704		case ALDPW, ASTPW:
  6705			if vo < -256 || vo > 252 || vo%4 != 0 {
  6706				c.ctxt.Diag("invalid offset %v\n", p)
  6707			}
  6708			vo /= 4
  6709			ret = 0
  6710		case ALDPSW:
  6711			if vo < -256 || vo > 252 || vo%4 != 0 {
  6712				c.ctxt.Diag("invalid offset %v\n", p)
  6713			}
  6714			vo /= 4
  6715			ret = 1 << 30
  6716		default:
  6717			c.ctxt.Diag("invalid instruction %v\n", p)
  6718		}
  6719		// check register pair
  6720		switch p.As {
  6721		case AFLDPD, AFLDPS, AFSTPD, AFSTPS:
  6722			if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
  6723				c.ctxt.Diag("invalid register pair %v\n", p)
  6724			}
  6725		case ALDP, ALDPW, ALDPSW:
  6726			if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
  6727				c.ctxt.Diag("invalid register pair %v\n", p)
  6728			}
  6729		case ASTP, ASTPW:
  6730			if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
  6731				c.ctxt.Diag("invalid register pair %v\n", p)
  6732			}
  6733		}
  6734		// other conditional flag bits
  6735		switch o.scond {
  6736		case C_XPOST:
  6737			ret |= 1 << 23
  6738		case C_XPRE:
  6739			ret |= 3 << 23
  6740		default:
  6741			ret |= 2 << 23
  6742		}
  6743		ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
  6744		return ret
  6745	}
  6746	
  6747	/*
  6748	 * size in log2(bytes)
  6749	 */
  6750	func movesize(a obj.As) int {
  6751		switch a {
  6752		case AMOVD:
  6753			return 3
  6754	
  6755		case AMOVW, AMOVWU:
  6756			return 2
  6757	
  6758		case AMOVH, AMOVHU:
  6759			return 1
  6760	
  6761		case AMOVB, AMOVBU:
  6762			return 0
  6763	
  6764		case AFMOVS:
  6765			return 2
  6766	
  6767		case AFMOVD:
  6768			return 3
  6769	
  6770		default:
  6771			return -1
  6772		}
  6773	}
  6774	
  6775	// rm is the Rm register value, o is the extension, amount is the left shift value.
  6776	func roff(rm int16, o uint32, amount int16) uint32 {
  6777		return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
  6778	}
  6779	
  6780	// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
  6781	func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
  6782		var num, rm int16
  6783		num = (r >> 5) & 7
  6784		rm = r & 31
  6785		switch {
  6786		case REG_UXTB <= r && r < REG_UXTH:
  6787			return roff(rm, 0, num)
  6788		case REG_UXTH <= r && r < REG_UXTW:
  6789			return roff(rm, 1, num)
  6790		case REG_UXTW <= r && r < REG_UXTX:
  6791			if a.Type == obj.TYPE_MEM {
  6792				if num == 0 {
  6793					return roff(rm, 2, 2)
  6794				} else {
  6795					return roff(rm, 2, 6)
  6796				}
  6797			} else {
  6798				return roff(rm, 2, num)
  6799			}
  6800		case REG_UXTX <= r && r < REG_SXTB:
  6801			return roff(rm, 3, num)
  6802		case REG_SXTB <= r && r < REG_SXTH:
  6803			return roff(rm, 4, num)
  6804		case REG_SXTH <= r && r < REG_SXTW:
  6805			return roff(rm, 5, num)
  6806		case REG_SXTW <= r && r < REG_SXTX:
  6807			if a.Type == obj.TYPE_MEM {
  6808				if num == 0 {
  6809					return roff(rm, 6, 2)
  6810				} else {
  6811					return roff(rm, 6, 6)
  6812				}
  6813			} else {
  6814				return roff(rm, 6, num)
  6815			}
  6816		case REG_SXTX <= r && r < REG_SPECIAL:
  6817			if a.Type == obj.TYPE_MEM {
  6818				if num == 0 {
  6819					return roff(rm, 7, 2)
  6820				} else {
  6821					return roff(rm, 7, 6)
  6822				}
  6823			} else {
  6824				return roff(rm, 7, num)
  6825			}
  6826		case REG_LSL <= r && r < (REG_LSL+1<<8):
  6827			return roff(rm, 3, 6)
  6828		default:
  6829			c.ctxt.Diag("unsupported register extension type.")
  6830		}
  6831	
  6832		return 0
  6833	}
  6834	

View as plain text