github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/cmd/internal/obj/sparc64/asm.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sparc64
     6  
     7  import (
     8  	"cmd/internal/obj"
     9  	"errors"
    10  	"fmt"
    11  	"sort"
    12  )
    13  
    14  type Optab struct {
    15  	as obj.As // instruction
    16  	a1 int8   // from
    17  	a2 int8   // reg
    18  	a3 int8   // from3
    19  	a4 int8   // to
    20  }
    21  
    22  type OptabSlice []Optab
    23  
    24  func (tab OptabSlice) Len() int { return len(tab) }
    25  
    26  func (tab OptabSlice) Swap(i, j int) { tab[i], tab[j] = tab[j], tab[i] }
    27  
    28  func (tab OptabSlice) Less(i, j int) bool {
    29  	return ocmp(tab[i], tab[j])
    30  }
    31  
    32  func ocmp(o1, o2 Optab) bool {
    33  	if o1.as != o2.as {
    34  		return o1.as < o2.as
    35  	}
    36  	if o1.a1 != o2.a1 {
    37  		return o1.a1 < o2.a1
    38  	}
    39  	if o1.a2 != o2.a2 {
    40  		return o1.a2 < o2.a2
    41  	}
    42  	if o1.a3 != o2.a3 {
    43  		return o1.a3 < o2.a3
    44  	}
    45  	return o1.a4 < o2.a4
    46  }
    47  
    48  type Opval struct {
    49  	op     int8 // selects case in asmout switch
    50  	size   int8 // *not* including delay-slot
    51  	OpInfo      // information about the instruction
    52  }
    53  
    54  type OpInfo int8
    55  
    56  const (
    57  	ClobberTMP OpInfo = 1 << iota
    58  )
    59  
    60  var optab = map[Optab]Opval{
    61  	Optab{obj.ATEXT, ClassAddr, ClassNone, ClassNone, ClassTextSize}: {0, 0, 0},
    62  	Optab{obj.AFUNCDATA, ClassConst, ClassNone, ClassNone, ClassMem}: {0, 0, 0},
    63  	Optab{obj.APCDATA, ClassConst, ClassNone, ClassNone, ClassConst}: {0, 0, 0},
    64  
    65  	Optab{AADD, ClassReg, ClassNone, ClassNone, ClassReg}:  {1, 4, 0},
    66  	Optab{AAND, ClassReg, ClassNone, ClassNone, ClassReg}:  {1, 4, 0},
    67  	Optab{AMULD, ClassReg, ClassNone, ClassNone, ClassReg}: {1, 4, 0},
    68  	Optab{ASLLD, ClassReg, ClassNone, ClassNone, ClassReg}: {1, 4, 0},
    69  	Optab{ASLLW, ClassReg, ClassNone, ClassNone, ClassReg}: {1, 4, 0},
    70  	Optab{AADD, ClassReg, ClassReg, ClassNone, ClassReg}:   {1, 4, 0},
    71  	Optab{AAND, ClassReg, ClassReg, ClassNone, ClassReg}:   {1, 4, 0},
    72  	Optab{AMULD, ClassReg, ClassReg, ClassNone, ClassReg}:  {1, 4, 0},
    73  	Optab{ASLLD, ClassReg, ClassReg, ClassNone, ClassReg}:  {1, 4, 0},
    74  	Optab{ASLLW, ClassReg, ClassReg, ClassNone, ClassReg}:  {1, 4, 0},
    75  
    76  	Optab{ASAVE, ClassReg, ClassReg, ClassNone, ClassReg}: {1, 4, 0},
    77  	Optab{ASAVE, ClassReg, ClassReg | ClassBias, ClassNone, ClassReg | ClassBias}: {1, 4, 0},
    78  
    79  	Optab{AFADDD, ClassDReg, ClassNone, ClassNone, ClassDReg}:  {1, 4, 0},
    80  	Optab{AFADDD, ClassDReg, ClassDReg, ClassNone, ClassDReg}:  {1, 4, 0},
    81  	Optab{AFSMULD, ClassFReg, ClassFReg, ClassNone, ClassDReg}: {1, 4, 0},
    82  
    83  	Optab{AMOVD, ClassReg, ClassNone, ClassNone, ClassReg}: {2, 4, 0},
    84  
    85  	Optab{AADD, ClassConst13, ClassNone, ClassNone, ClassReg}:  {3, 4, 0},
    86  	Optab{AAND, ClassConst13, ClassNone, ClassNone, ClassReg}:  {3, 4, 0},
    87  	Optab{AMULD, ClassConst13, ClassNone, ClassNone, ClassReg}: {3, 4, 0},
    88  	Optab{ASLLD, ClassConst6, ClassNone, ClassNone, ClassReg}:  {3, 4, 0},
    89  	Optab{ASLLW, ClassConst5, ClassNone, ClassNone, ClassReg}:  {3, 4, 0},
    90  	Optab{AADD, ClassConst13, ClassReg, ClassNone, ClassReg}:   {3, 4, 0},
    91  	Optab{AAND, ClassConst13, ClassReg, ClassNone, ClassReg}:   {3, 4, 0},
    92  	Optab{AMULD, ClassConst13, ClassReg, ClassNone, ClassReg}:  {3, 4, 0},
    93  	Optab{ASLLD, ClassConst6, ClassReg, ClassNone, ClassReg}:   {3, 4, 0},
    94  	Optab{ASLLW, ClassConst5, ClassReg, ClassNone, ClassReg}:   {3, 4, 0},
    95  
    96  	Optab{ASAVE, ClassConst13, ClassReg, ClassNone, ClassReg}: {3, 4, 0},
    97  	Optab{ASAVE, ClassConst13, ClassReg | ClassBias, ClassNone, ClassReg | ClassBias}: {3, 4, 0},
    98  
    99  	Optab{AMOVD, ClassConst13, ClassNone, ClassNone, ClassReg}: {4, 4, 0},
   100  	Optab{AMOVW, ClassConst13, ClassNone, ClassNone, ClassReg}: {4, 4, 0},
   101  
   102  	Optab{ALDD, ClassIndirRegReg, ClassNone, ClassNone, ClassReg}:   {5, 4, 0},
   103  	Optab{ASTD, ClassReg, ClassNone, ClassNone, ClassIndirRegReg}:   {6, 4, 0},
   104  	Optab{ALDDF, ClassIndirRegReg, ClassNone, ClassNone, ClassDReg}: {5, 4, 0},
   105  	Optab{ASTDF, ClassDReg, ClassNone, ClassNone, ClassIndirRegReg}: {6, 4, 0},
   106  
   107  	Optab{ALDD, ClassIndir13, ClassNone, ClassNone, ClassReg}:   {7, 4, 0},
   108  	Optab{ASTD, ClassReg, ClassNone, ClassNone, ClassIndir13}:   {8, 4, 0},
   109  	Optab{ALDDF, ClassIndir13, ClassNone, ClassNone, ClassDReg}: {7, 4, 0},
   110  	Optab{ASTDF, ClassDReg, ClassNone, ClassNone, ClassIndir13}: {8, 4, 0},
   111  
   112  	Optab{ARD, ClassSpcReg, ClassNone, ClassNone, ClassReg}: {9, 4, 0},
   113  
   114  	Optab{ACASD, ClassIndir0, ClassReg, ClassNone, ClassReg}: {10, 4, 0},
   115  
   116  	Optab{AFSTOD, ClassFReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   117  	Optab{AFDTOS, ClassDReg, ClassNone, ClassNone, ClassFReg}: {11, 4, 0},
   118  
   119  	Optab{AFMOVD, ClassDReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   120  
   121  	Optab{AFXTOD, ClassDReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   122  	Optab{AFITOD, ClassFReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   123  	Optab{AFXTOS, ClassDReg, ClassNone, ClassNone, ClassFReg}: {11, 4, 0},
   124  	Optab{AFITOS, ClassFReg, ClassNone, ClassNone, ClassFReg}: {11, 4, 0},
   125  
   126  	Optab{AFSTOX, ClassFReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   127  	Optab{AFDTOX, ClassDReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   128  	Optab{AFDTOI, ClassDReg, ClassNone, ClassNone, ClassFReg}: {11, 4, 0},
   129  	Optab{AFSTOI, ClassFReg, ClassNone, ClassNone, ClassFReg}: {11, 4, 0},
   130  
   131  	Optab{AFABSD, ClassDReg, ClassNone, ClassNone, ClassDReg}: {11, 4, 0},
   132  
   133  	Optab{ASETHI, ClassConst32, ClassNone, ClassNone, ClassReg}: {12, 4, 0},
   134  	Optab{ARNOP, ClassNone, ClassNone, ClassNone, ClassNone}:    {12, 4, 0},
   135  	Optab{AFLUSHW, ClassNone, ClassNone, ClassNone, ClassNone}:  {12, 4, 0},
   136  
   137  	Optab{AMEMBAR, ClassConst, ClassNone, ClassNone, ClassNone}: {13, 4, 0},
   138  
   139  	Optab{AFCMPD, ClassDReg, ClassDReg, ClassNone, ClassFCond}: {14, 4, 0},
   140  	Optab{AFCMPD, ClassDReg, ClassDReg, ClassNone, ClassNone}:  {14, 4, 0},
   141  
   142  	Optab{AMOVD, ClassConst32, ClassNone, ClassNone, ClassReg}:  {15, 8, 0},
   143  	Optab{AMOVD, ClassConst31_, ClassNone, ClassNone, ClassReg}: {16, 8, 0},
   144  
   145  	Optab{obj.AJMP, ClassNone, ClassNone, ClassNone, ClassBranch}: {17, 4, 0},
   146  	Optab{ABN, ClassCond, ClassNone, ClassNone, ClassBranch}:      {17, 4, 0},
   147  	Optab{ABNW, ClassNone, ClassNone, ClassNone, ClassBranch}:     {17, 4, 0},
   148  	Optab{ABRZ, ClassReg, ClassNone, ClassNone, ClassBranch}:      {18, 4, 0},
   149  	Optab{AFBA, ClassNone, ClassNone, ClassNone, ClassBranch}:     {19, 4, 0},
   150  
   151  	Optab{AJMPL, ClassReg, ClassNone, ClassNone, ClassReg}:        {20, 4, 0},
   152  	Optab{AJMPL, ClassRegConst13, ClassNone, ClassNone, ClassReg}: {20, 4, 0},
   153  	Optab{AJMPL, ClassRegReg, ClassNone, ClassNone, ClassReg}:     {21, 4, 0},
   154  
   155  	Optab{obj.ACALL, ClassNone, ClassNone, ClassNone, ClassMem}:     {22, 4, 0},
   156  	Optab{obj.ADUFFZERO, ClassNone, ClassNone, ClassNone, ClassMem}: {22, 4, 0},
   157  	Optab{obj.ADUFFCOPY, ClassNone, ClassNone, ClassNone, ClassMem}: {22, 4, 0},
   158  
   159  	Optab{AMOVD, ClassAddr, ClassNone, ClassNone, ClassReg}: {23, 24, ClobberTMP},
   160  
   161  	Optab{ALDD, ClassMem, ClassNone, ClassNone, ClassReg}:   {24, 28, ClobberTMP},
   162  	Optab{ALDDF, ClassMem, ClassNone, ClassNone, ClassDReg}: {24, 28, ClobberTMP},
   163  	Optab{ASTD, ClassReg, ClassNone, ClassNone, ClassMem}:   {25, 28, ClobberTMP},
   164  	Optab{ASTDF, ClassDReg, ClassNone, ClassNone, ClassMem}: {25, 28, ClobberTMP},
   165  
   166  	Optab{obj.ARET, ClassNone, ClassNone, ClassNone, ClassNone}: {26, 4, 0},
   167  
   168  	Optab{ATA, ClassConst13, ClassNone, ClassNone, ClassNone}: {27, 4, 0},
   169  
   170  	Optab{AMOVD, ClassRegConst13, ClassNone, ClassNone, ClassReg}: {28, 4, 0},
   171  
   172  	Optab{AMOVUB, ClassReg, ClassNone, ClassNone, ClassReg}: {29, 4, 0},
   173  	Optab{AMOVUH, ClassReg, ClassNone, ClassNone, ClassReg}: {30, 8, 0},
   174  	Optab{AMOVUW, ClassReg, ClassNone, ClassNone, ClassReg}: {31, 4, 0},
   175  
   176  	Optab{AMOVB, ClassReg, ClassNone, ClassNone, ClassReg}: {32, 8, 0},
   177  	Optab{AMOVH, ClassReg, ClassNone, ClassNone, ClassReg}: {33, 8, 0},
   178  	Optab{AMOVW, ClassReg, ClassNone, ClassNone, ClassReg}: {34, 4, 0},
   179  
   180  	Optab{ANEG, ClassReg, ClassNone, ClassNone, ClassReg}: {35, 4, 0},
   181  
   182  	Optab{ACMP, ClassReg, ClassReg, ClassNone, ClassNone}:     {36, 4, 0},
   183  	Optab{ACMP, ClassConst13, ClassReg, ClassNone, ClassNone}: {37, 4, 0},
   184  
   185  	Optab{ABND, ClassNone, ClassNone, ClassNone, ClassBranch}: {38, 4, 0},
   186  
   187  	Optab{obj.AUNDEF, ClassNone, ClassNone, ClassNone, ClassNone}: {39, 4, 0},
   188  
   189  	Optab{obj.ACALL, ClassNone, ClassNone, ClassNone, ClassReg}:    {40, 4, 0},
   190  	Optab{obj.ACALL, ClassReg, ClassNone, ClassNone, ClassReg}:     {40, 4, 0},
   191  	Optab{obj.ACALL, ClassNone, ClassNone, ClassNone, ClassIndir0}: {40, 4, 0},
   192  	Optab{obj.ACALL, ClassReg, ClassNone, ClassNone, ClassIndir0}:  {40, 4, 0},
   193  
   194  	Optab{AADD, ClassConst32, ClassNone, ClassNone, ClassReg}: {41, 12, ClobberTMP},
   195  	Optab{AAND, ClassConst32, ClassNone, ClassNone, ClassReg}: {41, 12, ClobberTMP},
   196  	Optab{AADD, ClassConst32, ClassReg, ClassNone, ClassReg}:  {41, 12, ClobberTMP},
   197  	Optab{AAND, ClassConst32, ClassReg, ClassNone, ClassReg}:  {41, 12, ClobberTMP},
   198  
   199  	Optab{AMOVD, ClassRegConst, ClassNone, ClassNone, ClassReg}: {42, 12, ClobberTMP},
   200  
   201  	Optab{ASTD, ClassReg, ClassNone, ClassNone, ClassIndir}:   {43, 12, ClobberTMP},
   202  	Optab{ASTDF, ClassDReg, ClassNone, ClassNone, ClassIndir}: {43, 12, ClobberTMP},
   203  	Optab{ALDD, ClassIndir, ClassNone, ClassNone, ClassReg}:   {44, 12, ClobberTMP},
   204  	Optab{ALDDF, ClassIndir, ClassNone, ClassNone, ClassDReg}: {44, 12, ClobberTMP},
   205  
   206  	Optab{obj.AJMP, ClassNone, ClassNone, ClassNone, ClassMem}: {45, 28, ClobberTMP},
   207  
   208  	Optab{AMOVA, ClassCond, ClassNone, ClassConst11, ClassReg}: {46, 4, 0},
   209  	Optab{AMOVA, ClassCond, ClassReg, ClassNone, ClassReg}:     {47, 4, 0},
   210  
   211  	Optab{AMOVRZ, ClassReg, ClassNone, ClassConst10, ClassReg}: {48, 4, 0},
   212  	Optab{AMOVRZ, ClassReg, ClassReg, ClassNone, ClassReg}:     {49, 4, 0},
   213  
   214  	Optab{AMOVD, ClassTLSAddr, ClassNone, ClassNone, ClassReg}: {50, 12, 0},
   215  
   216  	Optab{ARETRESTORE, ClassNone, ClassNone, ClassNone, ClassNone}: {51, 12, 0},
   217  
   218  	Optab{obj.AJMP, ClassNone, ClassNone, ClassNone, ClassLargeBranch}: {52, 28, ClobberTMP},
   219  	Optab{ABN, ClassCond, ClassNone, ClassNone, ClassLargeBranch}:  {53, 48, ClobberTMP},
   220  	Optab{ABNW, ClassNone, ClassNone, ClassNone, ClassLargeBranch}: {53, 48, ClobberTMP},
   221  	Optab{ABRZ, ClassReg, ClassNone, ClassNone, ClassLargeBranch}:  {54, 48, ClobberTMP},
   222  	Optab{AFBA, ClassNone, ClassNone, ClassNone, ClassLargeBranch}: {55, 48, ClobberTMP},
   223  	Optab{ABND, ClassNone, ClassNone, ClassNone, ClassLargeBranch}: {56, 48, ClobberTMP},
   224  
   225  	Optab{obj.ACALL, ClassNone, ClassNone, ClassNone, ClassBranch}:      {57, 4, 0},
   226  	Optab{obj.ACALL, ClassNone, ClassNone, ClassNone, ClassLargeBranch}: {57, 4, 0},
   227  }
   228  
   229  // Compatible classes, if something accepts a $hugeconst, it
   230  // can also accept $smallconst, $0 and ZR. Something that accepts a
   231  // register, can also accept $0, etc.
   232  var cc = map[int8][]int8{
   233  	ClassReg:         {ClassZero},
   234  	ClassConst6:      {ClassConst5, ClassZero},
   235  	ClassConst10:     {ClassConst6, ClassConst5, ClassZero},
   236  	ClassConst11:     {ClassConst10, ClassConst6, ClassConst5, ClassZero},
   237  	ClassConst13:     {ClassConst11, ClassConst10, ClassConst6, ClassConst5, ClassZero},
   238  	ClassConst31:     {ClassConst6, ClassConst5, ClassZero},
   239  	ClassConst32:     {ClassConst31_, ClassConst31, ClassConst13, ClassConst11, ClassConst10, ClassConst6, ClassConst5, ClassZero},
   240  	ClassConst:       {ClassConst32, ClassConst31_, ClassConst31, ClassConst13, ClassConst11, ClassConst10, ClassConst6, ClassConst5, ClassZero},
   241  	ClassRegConst:    {ClassRegConst13},
   242  	ClassIndir13:     {ClassIndir0},
   243  	ClassIndir:       {ClassIndir13, ClassIndir0},
   244  	ClassLargeBranch: {ClassBranch},
   245  }
   246  
   247  func isAddrCompatible(ctxt *obj.Link, a *obj.Addr, class int8) bool {
   248  	cls := aclass(ctxt, a)
   249  	cls &= ^ClassBias
   250  	if cls == class {
   251  		return true
   252  	}
   253  	for _, v := range cc[class] {
   254  		if cls == v {
   255  			return true
   256  		}
   257  	}
   258  	return false
   259  }
   260  
   261  var isInstDouble = map[obj.As]bool{
   262  	AFADDD:  true,
   263  	AFSUBD:  true,
   264  	AFABSD:  true,
   265  	AFCMPD:  true,
   266  	AFDIVD:  true,
   267  	AFMOVD:  true,
   268  	AFMULD:  true,
   269  	AFNEGD:  true,
   270  	AFSQRTD: true,
   271  	ALDDF:   true,
   272  	ASTDF:   true,
   273  }
   274  
   275  var isInstFloat = map[obj.As]bool{
   276  	AFADDS:  true,
   277  	AFSUBS:  true,
   278  	AFABSS:  true,
   279  	AFCMPS:  true,
   280  	AFDIVS:  true,
   281  	AFMOVS:  true,
   282  	AFMULS:  true,
   283  	AFNEGS:  true,
   284  	AFSQRTS: true,
   285  	ALDSF:   true,
   286  	ASTSF:   true,
   287  }
   288  
   289  var isSrcDouble = map[obj.As]bool{
   290  	AFXTOD: true,
   291  	AFXTOS: true,
   292  	AFDTOX: true,
   293  	AFDTOI: true,
   294  	AFDTOS: true,
   295  }
   296  
   297  var isSrcFloat = map[obj.As]bool{
   298  	AFITOD: true,
   299  	AFITOS: true,
   300  	AFSTOX: true,
   301  	AFSTOI: true,
   302  	AFSTOD: true,
   303  }
   304  
   305  var isDstDouble = map[obj.As]bool{
   306  	AFXTOD: true,
   307  	AFITOD: true,
   308  	AFSTOX: true,
   309  	AFDTOX: true,
   310  	AFSTOD: true,
   311  }
   312  
   313  var isDstFloat = map[obj.As]bool{
   314  	AFXTOS: true,
   315  	AFITOS: true,
   316  	AFDTOI: true,
   317  	AFSTOI: true,
   318  	AFDTOS: true,
   319  }
   320  
   321  // Compatible instructions, if an asm* function accepts AADD,
   322  // it accepts ASUBCCC too.
   323  var ci = map[obj.As][]obj.As{
   324  	AADD:   {AADDCC, AADDC, AADDCCC, ASUB, ASUBCC, ASUBC, ASUBCCC},
   325  	AAND:   {AANDCC, AANDN, AANDNCC, AOR, AORCC, AORN, AORNCC, AXOR, AXORCC, AXNOR, AXNORCC},
   326  	ABN:    {ABNE, ABE, ABG, ABLE, ABGE, ABL, ABGU, ABLEU, ABCC, ABCS, ABPOS, ABNEG, ABVC, ABVS},
   327  	ABNW:   {ABNEW, ABEW, ABGW, ABLEW, ABGEW, ABLW, ABGUW, ABLEUW, ABCCW, ABCSW, ABPOSW, ABNEGW, ABVCW, ABVSW},
   328  	ABND:   {ABNED, ABED, ABGD, ABLED, ABGED, ABLD, ABGUD, ABLEUD, ABCCD, ABCSD, ABPOSD, ABNEGD, ABVCD, ABVSD},
   329  	ABRZ:   {ABRLEZ, ABRLZ, ABRNZ, ABRGZ, ABRGEZ},
   330  	ACASD:  {ACASW},
   331  	AFABSD: {AFABSS, AFNEGD, AFNEGS, AFSQRTD, AFNEGS},
   332  	AFADDD: {AFADDS, AFSUBS, AFSUBD, AFMULD, AFMULS, AFSMULD, AFDIVD, AFDIVS},
   333  	AFBA:   {AFBN, AFBU, AFBG, AFBUG, AFBL, AFBUL, AFBLG, AFBNE, AFBE, AFBUE, AFBGE, AFBUGE, AFBLE, AFBULE, AFBO},
   334  	AFCMPD: {AFCMPS},
   335  	AFITOD: {AFITOS},
   336  	AFMOVD: {AFMOVS},
   337  	AFSTOD: {AFDTOS},
   338  	AFXTOD: {AFXTOS},
   339  	ALDD:   {ALDSB, ALDSH, ALDSW, ALDUB, ALDUH, ALDUW, AMOVB, AMOVH, AMOVW, AMOVUB, AMOVUH, AMOVUW, AMOVD},
   340  	ALDDF:  {ALDSF, AFMOVD, AFMOVS},
   341  	AMOVA:  {AMOVN, AMOVNE, AMOVE, AMOVG, AMOVLE, AMOVGE, AMOVL, AMOVGU, AMOVLEU, AMOVCC, AMOVCS, AMOVPOS, AMOVNEG, AMOVVC, AMOVVS},
   342  	AMOVRZ: {AMOVRLEZ, AMOVRLZ, AMOVRNZ, AMOVRGZ, AMOVRGEZ},
   343  	AMULD:  {ASDIVD, AUDIVD},
   344  	ARD:    {AMOVD},
   345  	ASLLD:  {ASRLD, ASRAD},
   346  	ASLLW:  {ASLLW, ASRLW, ASRAW},
   347  	ASTD:   {ASTB, ASTH, ASTW, AMOVB, AMOVH, AMOVW, AMOVUB, AMOVUH, AMOVUW, AMOVD},
   348  	ASTDF:  {ASTSF, AFMOVD, AFMOVS},
   349  	ASAVE:  {ARESTORE},
   350  }
   351  
   352  func opkeys() OptabSlice {
   353  	keys := make(OptabSlice, 0, len(optab))
   354  	// create sorted map index by keys
   355  	for k := range optab {
   356  		keys = append(keys, k)
   357  	}
   358  	sort.Sort(keys)
   359  	return keys
   360  }
   361  
   362  func init() {
   363  	// For each line in optab, duplicate it so that we'll also
   364  	// have a line that will accept compatible instructions, but
   365  	// only if there isn't an already existent line with the same
   366  	// key. Also change operand type, if the instruction is a double.
   367  	for _, o := range opkeys() {
   368  		for _, c := range ci[o.as] {
   369  			do := o
   370  			do.as = c
   371  			if isInstDouble[o.as] && isInstFloat[do.as] {
   372  				if do.a1 == ClassDReg {
   373  					do.a1 = ClassFReg
   374  				}
   375  				if do.a2 == ClassDReg {
   376  					do.a2 = ClassFReg
   377  				}
   378  				if do.a3 == ClassDReg {
   379  					do.a3 = ClassFReg
   380  				}
   381  				if do.a4 == ClassDReg {
   382  					do.a4 = ClassFReg
   383  				}
   384  			}
   385  			_, ok := optab[do]
   386  			if !ok {
   387  				optab[do] = optab[o]
   388  			}
   389  		}
   390  	}
   391  	// For each line in optab that accepts a large-class operand,
   392  	// duplicate it so that we'll also have a line that accepts a
   393  	// small-class operand, but do it only if there isn't an already
   394  	// existent line with the same key.
   395  	for _, o := range opkeys() {
   396  		for _, c := range cc[o.a1] {
   397  			do := o
   398  			do.a1 = c
   399  			_, ok := optab[do]
   400  			if !ok {
   401  				optab[do] = optab[o]
   402  			}
   403  		}
   404  	}
   405  	for _, o := range opkeys() {
   406  		for _, c := range cc[o.a2] {
   407  			do := o
   408  			do.a2 = c
   409  			_, ok := optab[do]
   410  			if !ok {
   411  				optab[do] = optab[o]
   412  			}
   413  		}
   414  	}
   415  	for _, o := range opkeys() {
   416  		for _, c := range cc[o.a3] {
   417  			do := o
   418  			do.a3 = c
   419  			_, ok := optab[do]
   420  			if !ok {
   421  				optab[do] = optab[o]
   422  			}
   423  		}
   424  	}
   425  	for _, o := range opkeys() {
   426  		for _, c := range cc[o.a4] {
   427  			do := o
   428  			do.a4 = c
   429  			_, ok := optab[do]
   430  			if !ok {
   431  				optab[do] = optab[o]
   432  			}
   433  		}
   434  	}
   435  }
   436  
   437  func oplook(p *obj.Prog) (Opval, error) {
   438  	var a2, a3 int8 = ClassNone, ClassNone
   439  	if p.Reg != 0 {
   440  		a2 = rclass(p.Reg)
   441  	}
   442  	var type3 obj.AddrType
   443  	if p.From3 != nil {
   444  		a3 = p.From3.Class
   445  		type3 = p.From3.Type
   446  	}
   447  	o := Optab{as: p.As, a1: p.From.Class, a2: a2, a3: a3, a4: p.To.Class}
   448  	v, ok := optab[o]
   449  	if !ok {
   450  		return Opval{}, fmt.Errorf("illegal combination %v %v %v %v %v, %d %d %d %d", p, DRconv(o.a1), DRconv(o.a2), DRconv(o.a3), DRconv(o.a4), p.From.Type, p.Reg, type3, p.To.Type)
   451  	}
   452  	return v, nil
   453  }
   454  
   455  func ir(imm22 uint32, rd int16) uint32 {
   456  	return uint32(rd)&31<<25 | uint32(imm22&(1<<23-1))
   457  }
   458  
   459  func d22(a, disp22 int) uint32 {
   460  	return uint32(a&1<<29 | disp22&(1<<23-1))
   461  }
   462  
   463  func d19(a, cc1, cc0, p, disp19 int) uint32 {
   464  	return uint32(a&1<<29 | cc1&1<<21 | cc0&1<<20 | p&1<<19 | disp19&(1<<20-1))
   465  }
   466  
   467  func d30(disp30 int) uint32 {
   468  	return uint32(disp30 & (1<<31 - 1))
   469  }
   470  
   471  func rrr(rs1, imm_asi, rs2, rd int16) uint32 {
   472  	return uint32(uint32(rd)&31<<25 | uint32(rs1)&31<<14 | uint32(imm_asi)&255<<5 | uint32(rs2)&31)
   473  }
   474  
   475  func rsr(rs1 int16, simm13 int64, rd int16) uint32 {
   476  	return uint32(int(rd)&31<<25 | int(rs1)&31<<14 | 1<<13 | int(simm13)&(1<<14-1))
   477  }
   478  
   479  func rd(r int16) uint32 {
   480  	return uint32(int(r) & 31 << 25)
   481  }
   482  
   483  func op(op int) uint32 {
   484  	return uint32(op << 30)
   485  }
   486  
   487  func op3(op, op3 int) uint32 {
   488  	return uint32(op<<30 | op3<<19)
   489  }
   490  
   491  func op2(op2 int) uint32 {
   492  	return uint32(op2 << 22)
   493  }
   494  
   495  func cond(cond int) uint32 {
   496  	return uint32(cond << 25)
   497  }
   498  
   499  func opf(opf int) uint32 {
   500  	return uint32(opf << 5)
   501  }
   502  
   503  func opload(a obj.As) uint32 {
   504  	switch a {
   505  	// Load integer.
   506  	case ALDSB, AMOVB:
   507  		return op3(3, 9)
   508  	case ALDSH, AMOVH:
   509  		return op3(3, 10)
   510  	case ALDSW, AMOVW:
   511  		return op3(3, 8)
   512  	case ALDUB, AMOVUB:
   513  		return op3(3, 1)
   514  	case ALDUH, AMOVUH:
   515  		return op3(3, 2)
   516  	case ALDUW, AMOVUW:
   517  		return op3(3, 0)
   518  	case ALDD, AMOVD:
   519  		return op3(3, 11)
   520  
   521  	// Load floating-point register.
   522  	case ALDSF, AFMOVS:
   523  		return op3(3, 0x20)
   524  	case ALDDF, AFMOVD:
   525  		return op3(3, 0x23)
   526  
   527  	default:
   528  		panic("unknown instruction: " + obj.Aconv(a))
   529  	}
   530  }
   531  
   532  func opstore(a obj.As) uint32 {
   533  	switch a {
   534  	// Store Integer.
   535  	case ASTB, AMOVB, AMOVUB:
   536  		return op3(3, 5)
   537  	case ASTH, AMOVH, AMOVUH:
   538  		return op3(3, 6)
   539  	case ASTW, AMOVW, AMOVUW:
   540  		return op3(3, 4)
   541  	case ASTD, AMOVD:
   542  		return op3(3, 14)
   543  
   544  	// Store floating-point.
   545  	case ASTSF, AFMOVS:
   546  		return op3(3, 0x24)
   547  	case ASTDF, AFMOVD:
   548  		return op3(3, 0x27)
   549  
   550  	default:
   551  		panic("unknown instruction: " + obj.Aconv(a))
   552  	}
   553  }
   554  
   555  func oprd(a obj.As) uint32 {
   556  	switch a {
   557  	// Read ancillary state register.
   558  	case ARD, AMOVD:
   559  		return op3(2, 0x28)
   560  
   561  	default:
   562  		panic("unknown instruction: " + obj.Aconv(a))
   563  	}
   564  }
   565  
   566  func opalu(a obj.As) uint32 {
   567  	switch a {
   568  	// Add.
   569  	case AADD:
   570  		return op3(2, 0)
   571  	case AADDCC:
   572  		return op3(2, 16)
   573  	case AADDC:
   574  		return op3(2, 8)
   575  	case AADDCCC:
   576  		return op3(2, 24)
   577  
   578  	// AND logical operation.
   579  	case AAND:
   580  		return op3(2, 1)
   581  	case AANDCC:
   582  		return op3(2, 17)
   583  	case AANDN:
   584  		return op3(2, 5)
   585  	case AANDNCC:
   586  		return op3(2, 21)
   587  
   588  	// Multiply and divide.
   589  	case AMULD:
   590  		return op3(2, 9)
   591  	case ASDIVD:
   592  		return op3(2, 0x2D)
   593  	case AUDIVD:
   594  		return op3(2, 0xD)
   595  
   596  	// OR logical operation.
   597  	case AOR, AMOVD, AMOVW:
   598  		return op3(2, 2)
   599  	case AORCC:
   600  		return op3(2, 18)
   601  	case AORN:
   602  		return op3(2, 6)
   603  	case AORNCC:
   604  		return op3(2, 22)
   605  
   606  	// Subtract.
   607  	case ASUB:
   608  		return op3(2, 4)
   609  	case ASUBCC:
   610  		return op3(2, 20)
   611  	case ASUBC:
   612  		return op3(2, 12)
   613  	case ASUBCCC:
   614  		return op3(2, 28)
   615  
   616  	// XOR logical operation.
   617  	case AXOR:
   618  		return op3(2, 3)
   619  	case AXORCC:
   620  		return op3(2, 19)
   621  	case AXNOR:
   622  		return op3(2, 7)
   623  	case AXNORCC:
   624  		return op3(2, 23)
   625  
   626  	// Floating-Point Add
   627  	case AFADDS:
   628  		return op3(2, 0x34) | opf(0x41)
   629  	case AFADDD:
   630  		return op3(2, 0x34) | opf(0x42)
   631  
   632  	// Floating-point subtract.
   633  	case AFSUBS:
   634  		return op3(2, 0x34) | opf(0x45)
   635  	case AFSUBD:
   636  		return op3(2, 0x34) | opf(0x46)
   637  
   638  	// Floating-point divide.
   639  	case AFDIVS:
   640  		return op3(2, 0x34) | opf(0x4D)
   641  	case AFDIVD:
   642  		return op3(2, 0x34) | opf(0x4E)
   643  
   644  	// Floating-point multiply.
   645  	case AFMULS:
   646  		return op3(2, 0x34) | opf(0x49)
   647  	case AFMULD:
   648  		return op3(2, 0x34) | opf(0x4A)
   649  	case AFSMULD:
   650  		return op3(2, 0x34) | opf(0x69)
   651  
   652  	// Shift.
   653  	case ASLLW:
   654  		return op3(2, 0x25)
   655  	case ASRLW:
   656  		return op3(2, 0x26)
   657  	case ASRAW:
   658  		return op3(2, 0x27)
   659  	case ASLLD:
   660  		return op3(2, 0x25) | 1<<12
   661  	case ASRLD:
   662  		return op3(2, 0x26) | 1<<12
   663  	case ASRAD:
   664  		return op3(2, 0x27) | 1<<12
   665  
   666  	case ASAVE:
   667  		return op3(2, 0x3C)
   668  	case ARESTORE:
   669  		return op3(2, 0x3D)
   670  
   671  	default:
   672  		panic("unknown instruction: " + obj.Aconv(a))
   673  	}
   674  }
   675  
   676  func opcode(a obj.As) uint32 {
   677  	switch a {
   678  	// Branch on integer condition codes with prediction (BPcc).
   679  	case obj.AJMP:
   680  		return cond(8) | op2(1)
   681  	case ABN, ABNW, ABND:
   682  		return cond(0) | op2(1)
   683  	case ABNE, ABNEW, ABNED:
   684  		return cond(9) | op2(1)
   685  	case ABE, ABEW, ABED:
   686  		return cond(1) | op2(1)
   687  	case ABG, ABGW, ABGD:
   688  		return cond(10) | op2(1)
   689  	case ABLE, ABLEW, ABLED:
   690  		return cond(2) | op2(1)
   691  	case ABGE, ABGEW, ABGED:
   692  		return cond(11) | op2(1)
   693  	case ABL, ABLW, ABLD:
   694  		return cond(3) | op2(1)
   695  	case ABGU, ABGUW, ABGUD:
   696  		return cond(12) | op2(1)
   697  	case ABLEU, ABLEUW, ABLEUD:
   698  		return cond(4) | op2(1)
   699  	case ABCC, ABCCW, ABCCD:
   700  		return cond(13) | op2(1)
   701  	case ABCS, ABCSW, ABCSD:
   702  		return cond(5) | op2(1)
   703  	case ABPOS, ABPOSW, ABPOSD:
   704  		return cond(14) | op2(1)
   705  	case ABNEG, ABNEGW, ABNEGD:
   706  		return cond(6) | op2(1)
   707  	case ABVC, ABVCW, ABVCD:
   708  		return cond(15) | op2(1)
   709  	case ABVS, ABVSW, ABVSD:
   710  		return cond(7) | op2(1)
   711  
   712  	// Branch on integer register with prediction (BPr).
   713  	case ABRZ:
   714  		return cond(1) | op2(3)
   715  	case ABRLEZ:
   716  		return cond(2) | op2(3)
   717  	case ABRLZ:
   718  		return cond(3) | op2(3)
   719  	case ABRNZ:
   720  		return cond(5) | op2(3)
   721  	case ABRGZ:
   722  		return cond(6) | op2(3)
   723  	case ABRGEZ:
   724  		return cond(7) | op2(3)
   725  
   726  	// Call and link
   727  	case obj.ACALL, obj.ADUFFCOPY, obj.ADUFFZERO:
   728  		return op(1)
   729  
   730  	case ACASW:
   731  		return op3(3, 0x3C)
   732  	case ACASD:
   733  		return op3(3, 0x3E)
   734  
   735  	case AFABSS:
   736  		return op3(2, 0x34) | opf(9)
   737  	case AFABSD:
   738  		return op3(2, 0x34) | opf(10)
   739  
   740  	// Branch on floating-point condition codes (FBfcc).
   741  	case AFBA:
   742  		return cond(8) | op2(6)
   743  	case AFBN:
   744  		return cond(0) | op2(6)
   745  	case AFBU:
   746  		return cond(7) | op2(6)
   747  	case AFBG:
   748  		return cond(6) | op2(6)
   749  	case AFBUG:
   750  		return cond(5) | op2(6)
   751  	case AFBL:
   752  		return cond(4) | op2(6)
   753  	case AFBUL:
   754  		return cond(3) | op2(6)
   755  	case AFBLG:
   756  		return cond(2) | op2(6)
   757  	case AFBNE:
   758  		return cond(1) | op2(6)
   759  	case AFBE:
   760  		return cond(9) | op2(6)
   761  	case AFBUE:
   762  		return cond(10) | op2(6)
   763  	case AFBGE:
   764  		return cond(11) | op2(6)
   765  	case AFBUGE:
   766  		return cond(12) | op2(6)
   767  	case AFBLE:
   768  		return cond(13) | op2(6)
   769  	case AFBULE:
   770  		return cond(14) | op2(6)
   771  	case AFBO:
   772  		return cond(15) | op2(6)
   773  
   774  	// Floating-point compare.
   775  	case AFCMPS:
   776  		return op3(2, 0x35) | opf(0x51)
   777  	case AFCMPD:
   778  		return op3(2, 0x35) | opf(0x52)
   779  
   780  	// Convert 32-bit integer to floating point.
   781  	case AFITOS:
   782  		return op3(2, 0x34) | opf(0xC4)
   783  	case AFITOD:
   784  		return op3(2, 0x34) | opf(0xC8)
   785  
   786  	case AFLUSH:
   787  		return op3(2, 0x3B)
   788  
   789  	case AFLUSHW:
   790  		return op3(2, 0x2B)
   791  
   792  	// Floating-point move.
   793  	case AFMOVS:
   794  		return op3(2, 0x34) | opf(1)
   795  	case AFMOVD:
   796  		return op3(2, 0x34) | opf(2)
   797  
   798  	// Floating-point negate.
   799  	case AFNEGS:
   800  		return op3(2, 0x34) | opf(5)
   801  	case AFNEGD:
   802  		return op3(2, 0x34) | opf(6)
   803  
   804  	// Floating-point square root.
   805  	case AFSQRTS:
   806  		return op3(2, 0x34) | opf(0x29)
   807  	case AFSQRTD:
   808  		return op3(2, 0x34) | opf(0x2A)
   809  
   810  	// Convert floating-point to integer.
   811  	case AFSTOX:
   812  		return op3(2, 0x34) | opf(0x81)
   813  	case AFDTOX:
   814  		return op3(2, 0x34) | opf(0x82)
   815  	case AFSTOI:
   816  		return op3(2, 0x34) | opf(0xD1)
   817  	case AFDTOI:
   818  		return op3(2, 0x34) | opf(0xD2)
   819  
   820  	// Convert between floating-point formats.
   821  	case AFSTOD:
   822  		return op3(2, 0x34) | opf(0xC9)
   823  	case AFDTOS:
   824  		return op3(2, 0x34) | opf(0xC6)
   825  
   826  	// Convert 64-bit integer to floating point.
   827  	case AFXTOS:
   828  		return op3(2, 0x34) | opf(0x84)
   829  	case AFXTOD:
   830  		return op3(2, 0x34) | opf(0x88)
   831  
   832  	// Jump and link.
   833  	case AJMPL:
   834  		return op3(2, 0x38)
   835  
   836  	// Move Integer Register on Condition (MOVcc).
   837  	case AMOVA:
   838  		return op3(2, 0x2C) | 8<<14 | 1<<18
   839  	case AMOVN:
   840  		return op3(2, 0x2C) | 0<<14 | 1<<18
   841  	case AMOVNE:
   842  		return op3(2, 0x2C) | 9<<14 | 1<<18
   843  	case AMOVE:
   844  		return op3(2, 0x2C) | 1<<14 | 1<<18
   845  	case AMOVG:
   846  		return op3(2, 0x2C) | 10<<14 | 1<<18
   847  	case AMOVLE:
   848  		return op3(2, 0x2C) | 2<<14 | 1<<18
   849  	case AMOVGE:
   850  		return op3(2, 0x2C) | 11<<14 | 1<<18
   851  	case AMOVL:
   852  		return op3(2, 0x2C) | 3<<14 | 1<<18
   853  	case AMOVGU:
   854  		return op3(2, 0x2C) | 12<<14 | 1<<18
   855  	case AMOVLEU:
   856  		return op3(2, 0x2C) | 4<<14 | 1<<18
   857  	case AMOVCC:
   858  		return op3(2, 0x2C) | 13<<14 | 1<<18
   859  	case AMOVCS:
   860  		return op3(2, 0x2C) | 5<<14 | 1<<18
   861  	case AMOVPOS:
   862  		return op3(2, 0x2C) | 14<<14 | 1<<18
   863  	case AMOVNEG:
   864  		return op3(2, 0x2C) | 6<<14 | 1<<18
   865  	case AMOVVC:
   866  		return op3(2, 0x2C) | 15<<14 | 1<<18
   867  	case AMOVVS:
   868  		return op3(2, 0x2C) | 7<<14 | 1<<18
   869  
   870  	// Move Integer Register on Register Condition (MOVr).
   871  	case AMOVRZ:
   872  		return op3(2, 0x2f) | 1<<10
   873  	case AMOVRLEZ:
   874  		return op3(2, 0x2f) | 2<<10
   875  	case AMOVRLZ:
   876  		return op3(2, 0x2f) | 3<<10
   877  	case AMOVRNZ:
   878  		return op3(2, 0x2f) | 5<<10
   879  	case AMOVRGZ:
   880  		return op3(2, 0x2f) | 6<<10
   881  	case AMOVRGEZ:
   882  		return op3(2, 0x2f) | 7<<10
   883  
   884  	// Memory Barrier.
   885  	case AMEMBAR:
   886  		return op3(2, 0x28) | 0xF<<14 | 1<<13
   887  
   888  	case ASETHI, ARNOP:
   889  		return op2(4)
   890  
   891  	// Trap on Integer Condition Codes (Tcc).
   892  	case ATA:
   893  		return op3(2, 0x3A)
   894  
   895  	default:
   896  		panic("unknown instruction: " + obj.Aconv(a))
   897  	}
   898  }
   899  
   900  func oregclass(offset int64) int8 {
   901  	if offset == 0 {
   902  		return ClassIndir0
   903  	}
   904  	if -4096 <= offset && offset <= 4095 {
   905  		return ClassIndir13
   906  	}
   907  	return ClassIndir
   908  }
   909  
   910  func addrclass(offset int64) int8 {
   911  	if -4096 <= offset && offset <= 4095 {
   912  		return ClassRegConst13
   913  	}
   914  	return ClassRegConst
   915  }
   916  
   917  func constclass(offset int64) int8 {
   918  	if 0 <= offset && offset <= 31 {
   919  		return ClassConst5
   920  	}
   921  	if 0 <= offset && offset <= 63 {
   922  		return ClassConst6
   923  	}
   924  	if -512 <= offset && offset <= 513 {
   925  		return ClassConst10
   926  	}
   927  	if -1024 <= offset && offset <= 1023 {
   928  		return ClassConst11
   929  	}
   930  	if -4096 <= offset && offset <= 4095 {
   931  		return ClassConst13
   932  	}
   933  	if -1<<31 <= offset && offset < 0 {
   934  		return ClassConst31_
   935  	}
   936  	if 0 <= offset && offset <= 1<<31-1 {
   937  		return ClassConst31
   938  	}
   939  	if 0 <= offset && offset <= 1<<32-1 {
   940  		return ClassConst32
   941  	}
   942  	return ClassConst
   943  }
   944  
   945  func rclass(r int16) int8 {
   946  	switch {
   947  	case r == REG_ZR:
   948  		return ClassZero
   949  	case REG_G1 <= r && r <= REG_I7:
   950  		return ClassReg
   951  	case REG_F0 <= r && r <= REG_F31:
   952  		return ClassFReg
   953  	case REG_D0 <= r && r <= REG_D62:
   954  		return ClassDReg
   955  	case r == REG_ICC || r == REG_XCC:
   956  		return ClassCond
   957  	case REG_FCC0 <= r && r <= REG_FCC3:
   958  		return ClassFCond
   959  	case r == REG_BSP || r == REG_BFP:
   960  		return ClassReg | ClassBias
   961  	case r >= REG_SPECIAL:
   962  		return ClassSpcReg
   963  	}
   964  	return ClassUnknown
   965  }
   966  
   967  func aclass(ctxt *obj.Link, a *obj.Addr) int8 {
   968  	switch a.Type {
   969  	case obj.TYPE_NONE:
   970  		return ClassNone
   971  
   972  	case obj.TYPE_REG:
   973  		return rclass(a.Reg)
   974  
   975  	case obj.TYPE_MEM:
   976  		switch a.Name {
   977  		case obj.NAME_EXTERN, obj.NAME_STATIC:
   978  			if a.Sym == nil {
   979  				return ClassUnknown
   980  			}
   981  			if a.Sym.Type == obj.STLSBSS {
   982  				return ClassTLSMem
   983  			}
   984  			return ClassMem
   985  
   986  		case obj.NAME_AUTO, obj.NAME_PARAM:
   987  			return aclass(ctxt, autoeditaddr(ctxt, a))
   988  
   989  		case obj.NAME_NONE:
   990  			if a.Scale == 1 {
   991  				return ClassIndirRegReg
   992  			}
   993  			return oregclass(a.Offset) | rclass(a.Reg)&ClassBias
   994  		}
   995  
   996  	case obj.TYPE_FCONST:
   997  		return ClassFConst
   998  
   999  	case obj.TYPE_TEXTSIZE:
  1000  		return ClassTextSize
  1001  
  1002  	case obj.TYPE_CONST, obj.TYPE_ADDR:
  1003  		switch a.Name {
  1004  		case obj.NAME_NONE:
  1005  			if a.Reg != 0 {
  1006  				if a.Reg == REG_ZR && a.Offset == 0 {
  1007  					return ClassZero
  1008  				}
  1009  				if a.Scale == 1 {
  1010  					return ClassRegReg
  1011  				}
  1012  				return addrclass(a.Offset) | rclass(a.Reg)&ClassBias
  1013  			}
  1014  			return constclass(a.Offset)
  1015  
  1016  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  1017  			if a.Sym == nil {
  1018  				return ClassUnknown
  1019  			}
  1020  			if a.Sym.Type == obj.STLSBSS {
  1021  				return ClassTLSAddr
  1022  			}
  1023  			return ClassAddr
  1024  
  1025  		case obj.NAME_AUTO, obj.NAME_PARAM:
  1026  			return aclass(ctxt, autoeditaddr(ctxt, a))
  1027  		}
  1028  	case obj.TYPE_BRANCH:
  1029  		if a.Class == ClassLargeBranch {
  1030  			// Set by span() after initial pcs have been calculated.
  1031  			return ClassLargeBranch
  1032  		}
  1033  		return ClassBranch
  1034  	}
  1035  	return ClassUnknown
  1036  }
  1037  
  1038  func span(ctxt *obj.Link, cursym *obj.LSym) {
  1039  	if cursym.Text == nil || cursym.Text.Link == nil { // handle external functions and ELF section symbols
  1040  		return
  1041  	}
  1042  
  1043  	var pc int64 // relative to entry point
  1044  	for p := cursym.Text.Link; p != nil; p = p.Link {
  1045  		o, err := oplook(autoeditprog(ctxt, p))
  1046  		if err != nil {
  1047  			ctxt.Diag(err.Error())
  1048  		}
  1049  		p.Pc = pc
  1050  		pc += int64(o.size)
  1051  	}
  1052  
  1053  	// Now that initial Pcs have been determined, reclassify branches that
  1054  	// exceed the standard 21-bit signed maximum offset and recalculate.
  1055  	pc = 0
  1056  	for p := cursym.Text.Link; p != nil; p = p.Link {
  1057  		if p.To.Type == obj.TYPE_BRANCH && p.To.Class == ClassBranch {
  1058  			var offset int64
  1059  			if p.Pcond != nil {
  1060  				offset = p.Pcond.Pc - p.Pc
  1061  			} else {
  1062  				// obj.brloop will set p.Pcond to nil for jumps
  1063  				// to the same instruction.
  1064  				offset = p.To.Val.(*obj.Prog).Pc - p.Pc
  1065  			}
  1066  			if offset < -1<<20 || offset > 1<<20-1 {
  1067  				// Ideally, this would be done in aclass(), but
  1068  				// we don't have access to p there or the pc
  1069  				// (yet) in most cases. oplook will use this to
  1070  				// transform the branch appropriately so that
  1071  				// asmout will perform a "large" branch.
  1072  				p.To.Class = ClassLargeBranch
  1073  			}
  1074  		}
  1075  
  1076  		o, err := oplook(autoeditprog(ctxt, p))
  1077  		if err != nil {
  1078  			ctxt.Diag(err.Error())
  1079  		}
  1080  
  1081  		p.Pc = pc
  1082  		pc += int64(o.size)
  1083  	}
  1084  
  1085  	cursym.Size = pc
  1086  	cursym.Grow(cursym.Size)
  1087  
  1088  	var text []uint32 // actual assembled bytes
  1089  	for p := cursym.Text.Link; p != nil; p = p.Link {
  1090  		p1 := autoeditprog(ctxt, p)
  1091  		o, _ := oplook(p1)
  1092  		out, err := asmout(p1, o, cursym)
  1093  		if err != nil {
  1094  			ctxt.Diag("span: can't assemble: %v\n\t%v", err, p)
  1095  		}
  1096  		text = append(text, out...)
  1097  	}
  1098  
  1099  	bp := cursym.P
  1100  	for _, v := range text {
  1101  		ctxt.Arch.ByteOrder.PutUint32(bp, v)
  1102  		bp = bp[4:]
  1103  	}
  1104  }
  1105  
  1106  // bigmove assembles a move of the constant part of addr into reg.
  1107  func bigmove(ctxt *obj.Link, addr *obj.Addr, reg int16) (out []uint32) {
  1108  	out = make([]uint32, 2)
  1109  	class := aclass(ctxt, addr)
  1110  	switch class {
  1111  	case ClassRegConst, ClassIndir:
  1112  		class = constclass(addr.Offset)
  1113  	}
  1114  	switch class {
  1115  	// MOVD $imm32, R ->
  1116  	// 	SETHI hi($imm32), R
  1117  	// 	OR R, lo($imm32), R
  1118  	case ClassConst31, ClassConst32:
  1119  		out[0] = opcode(ASETHI) | ir(uint32(addr.Offset)>>10, reg)
  1120  		out[1] = opalu(AOR) | rsr(reg, int64(addr.Offset&0x3FF), reg)
  1121  
  1122  	// MOVD -$imm31, R ->
  1123  	// 	SETHI hi(^$imm32), R
  1124  	// 	XOR R, lo($imm32)|0x1C00, R
  1125  	case ClassConst31_:
  1126  		out[0] = opcode(ASETHI) | ir(^(uint32(addr.Offset))>>10, reg)
  1127  		out[1] = opalu(AXOR) | rsr(reg, int64(uint32(addr.Offset)&0x3ff|0x1C00), reg)
  1128  	default:
  1129  		panic("unexpected operand class: " + DRconv(class))
  1130  	}
  1131  	return out
  1132  }
  1133  
  1134  func usesRegs(a *obj.Addr) bool {
  1135  	if a == nil {
  1136  		return false
  1137  	}
  1138  	switch a.Class {
  1139  	case ClassReg, ClassFReg, ClassDReg, ClassCond, ClassFCond, ClassSpcReg, ClassZero, ClassRegReg, ClassRegConst13, ClassRegConst, ClassIndirRegReg, ClassIndir0, ClassIndir13, ClassIndir:
  1140  		return true
  1141  	}
  1142  	return false
  1143  }
  1144  
  1145  func isTMP(r int16) bool {
  1146  	return r == REG_TMP || r == REG_TMP2
  1147  }
  1148  
  1149  func usesTMP(a *obj.Addr) bool {
  1150  	return usesRegs(a) && (isTMP(a.Reg) || isTMP(a.Index))
  1151  }
  1152  
  1153  func srcCount(p *obj.Prog) (c int) {
  1154  	if p.From.Type != obj.TYPE_NONE {
  1155  		c++
  1156  	}
  1157  	if p.Reg != obj.REG_NONE {
  1158  		c++
  1159  	}
  1160  	if p.From3Type() != obj.TYPE_NONE {
  1161  		c++
  1162  	}
  1163  	return c
  1164  }
  1165  
  1166  // largebranch assembles a branch to a pc that exceeds a 21-bit signed displacement
  1167  func largebranch(offset int64) ([]uint32, error) {
  1168  	if offset%4 != 0 {
  1169  		return nil, errors.New("branch target not mod 4")
  1170  	}
  1171  
  1172  	out := make([]uint32, 7)
  1173  	// We don't know where we are, and we don't want to emit a
  1174  	// reloc, so save %o7 since we may be in the function prologue,
  1175  	// then do a pc-relative call to determine current address,
  1176  	// then restore %o7 so that we can use the current address plus
  1177  	// the calculated offset to perform a "large" jump to the
  1178  	// desired location.
  1179  	out[0] = opalu(AMOVD) | rrr(REG_ZR, 0, REG_OLR, REG_TMP2)
  1180  	out[1] = opcode(obj.ACALL) | d30(1)
  1181  	out[2] = opalu(AMOVD) | rrr(REG_ZR, 0, REG_OLR, REG_TMP)
  1182  	out[3] = opalu(AMOVD) | rrr(REG_ZR, 0, REG_TMP2, REG_OLR)
  1183  	offset -= 4 // make branch relative to call
  1184  	class := constclass(offset)
  1185  	switch class {
  1186  	// 	SETHI hi($imm32), R
  1187  	// 	OR R, lo($imm32), R
  1188  	case ClassConst31, ClassConst32:
  1189  		out[4] = opcode(ASETHI) | ir(uint32(offset)>>10, REG_TMP2)
  1190  		out[5] = opalu(AOR) | rsr(REG_TMP2, int64(offset&0x3FF), REG_TMP2)
  1191  
  1192  	// 	SETHI hi(^$imm32), R
  1193  	// 	XOR R, lo($imm32)|0x1C00, R
  1194  	case ClassConst31_:
  1195  		out[4] = opcode(ASETHI) | ir(^(uint32(offset))>>10, REG_TMP2)
  1196  		out[5] = opalu(AXOR) | rsr(REG_TMP2, int64(uint32(offset)&0x3ff|0x1C00), REG_TMP2)
  1197  	default:
  1198  		panic("unexpected operand class: " + DRconv(class))
  1199  	}
  1200  	out[6] = opcode(AJMPL) | rrr(REG_TMP, 0, REG_TMP2, REG_ZR)
  1201  	return out, nil
  1202  }
  1203  
  1204  func asmout(p *obj.Prog, o Opval, cursym *obj.LSym) (out []uint32, err error) {
  1205  	out = make([]uint32, 12)
  1206  	o1 := &out[0]
  1207  	o2 := &out[1]
  1208  	o3 := &out[2]
  1209  	o4 := &out[3]
  1210  	o5 := &out[4]
  1211  	o6 := &out[5]
  1212  	o7 := &out[6]
  1213  	o8 := &out[7]
  1214  	o9 := &out[8]
  1215  	o10 := &out[9]
  1216  	o11 := &out[10]
  1217  	o12 := &out[11]
  1218  	if o.OpInfo == ClobberTMP {
  1219  		if usesTMP(&p.From) {
  1220  			return nil, fmt.Errorf("asmout: %q not allowed: synthetic instruction clobbers temporary registers", obj.Mconv(&p.From))
  1221  		}
  1222  		if isTMP(p.Reg) {
  1223  			return nil, fmt.Errorf("asmout: %q not allowed: synthetic instruction clobbers temporary registers", Rconv(int(p.Reg)))
  1224  		}
  1225  		if usesTMP(p.From3) {
  1226  			return nil, fmt.Errorf("asmout: %q not allowed: synthetic instruction clobbers temporary registers", obj.Mconv(p.From3))
  1227  		}
  1228  		if usesTMP(&p.To) {
  1229  			if p.From.Type == obj.TYPE_NONE || srcCount(p) < 2 {
  1230  				return nil, fmt.Errorf("asmout: illegal use of temporary register: synthetic instruction clobbers temporary registers")
  1231  			}
  1232  		}
  1233  	}
  1234  	switch o.op {
  1235  	default:
  1236  		return nil, fmt.Errorf("unknown asm %d in %v", o, p)
  1237  
  1238  	case 0: /* pseudo ops */
  1239  		break
  1240  
  1241  	// op Rs,       Rd	-> Rd = Rs op Rd
  1242  	// op Rs1, Rs2, Rd	-> Rd = Rs2 op Rs1
  1243  	case 1:
  1244  		reg := p.To.Reg
  1245  		if p.Reg != 0 {
  1246  			reg = p.Reg
  1247  		}
  1248  		*o1 = opalu(p.As) | rrr(reg, 0, p.From.Reg, p.To.Reg)
  1249  
  1250  	// MOVD Rs, Rd
  1251  	case 2:
  1252  		*o1 = opalu(p.As) | rrr(REG_ZR, 0, p.From.Reg, p.To.Reg)
  1253  
  1254  	// op $imm13, Rs, Rd	-> Rd = Rs op $imm13
  1255  	case 3:
  1256  		reg := p.To.Reg
  1257  		if p.Reg != 0 {
  1258  			reg = p.Reg
  1259  		}
  1260  		*o1 = opalu(p.As) | rsr(reg, p.From.Offset, p.To.Reg)
  1261  
  1262  	// MOVD $imm13, Rd
  1263  	case 4:
  1264  		*o1 = opalu(p.As) | rsr(REG_ZR, p.From.Offset, p.To.Reg)
  1265  
  1266  	// LDD (R1+R2), R	-> R = *(R1+R2)
  1267  	case 5:
  1268  		*o1 = opload(p.As) | rrr(p.From.Reg, 0, p.From.Index, p.To.Reg)
  1269  
  1270  	// STD R, (R1+R2)	-> *(R1+R2) = R
  1271  	case 6:
  1272  		*o1 = opstore(p.As) | rrr(p.To.Reg, 0, p.To.Index, p.From.Reg)
  1273  
  1274  	// LDD $imm13(Rs), R	-> R = *(Rs+$imm13)
  1275  	case 7:
  1276  		*o1 = opload(p.As) | rsr(p.From.Reg, p.From.Offset, p.To.Reg)
  1277  
  1278  	// STD Rs, $imm13(R)	-> *(R+$imm13) = Rs
  1279  	case 8:
  1280  		*o1 = opstore(p.As) | rsr(p.To.Reg, p.To.Offset, p.From.Reg)
  1281  
  1282  	// RD Rspecial, R
  1283  	case 9:
  1284  		*o1 = oprd(p.As) | uint32(p.From.Reg&0x1f)<<14 | rd(p.To.Reg)
  1285  
  1286  	// CASD/CASW
  1287  	case 10:
  1288  		*o1 = opcode(p.As) | rrr(p.From.Reg, 0x80, p.Reg, p.To.Reg)
  1289  
  1290  	// fop Fs, Fd
  1291  	case 11:
  1292  		*o1 = opcode(p.As) | rrr(0, 0, p.From.Reg, p.To.Reg)
  1293  
  1294  	// SETHI $const, R
  1295  	// RNOP
  1296  	case 12:
  1297  		if p.From.Offset&0x3FF != 0 {
  1298  			return nil, errors.New("SETHI constant not mod 1024")
  1299  		}
  1300  		*o1 = opcode(p.As) | ir(uint32(p.From.Offset)>>10, p.To.Reg)
  1301  
  1302  	// MEMBAR $mask
  1303  	case 13:
  1304  		if p.From.Offset > 127 {
  1305  			return nil, errors.New("MEMBAR mask out of range")
  1306  		}
  1307  		*o1 = opcode(p.As) | uint32(p.From.Offset)
  1308  
  1309  	// FCMPD F, F, FCC
  1310  	case 14:
  1311  		*o1 = opcode(p.As) | rrr(p.Reg, 0, p.From.Reg, p.To.Reg&3)
  1312  
  1313  	// MOVD $imm32, R
  1314  	// MOVD -$imm31, R
  1315  	case 15, 16:
  1316  		out := bigmove(p.Ctxt, &p.From, p.To.Reg)
  1317  		return out, nil
  1318  
  1319  	// BLE XCC, n(PC)
  1320  	// JMP n(PC)
  1321  	case 17:
  1322  		var offset int64
  1323  		if p.Pcond != nil {
  1324  			offset = p.Pcond.Pc - p.Pc
  1325  		} else {
  1326  			// obj.brloop will set p.Pcond to nil for jumps to the same instruction.
  1327  			offset = p.To.Val.(*obj.Prog).Pc - p.Pc
  1328  		}
  1329  		if offset < -1<<20 || offset > 1<<20-1 {
  1330  			return nil, errors.New("branch target out of range")
  1331  		}
  1332  		if offset%4 != 0 {
  1333  			return nil, errors.New("branch target not mod 4")
  1334  		}
  1335  		*o1 = opcode(p.As) | uint32(p.From.Reg&3)<<20 | uint32(offset>>2)&(1<<19-1)
  1336  		// default is to predict branch taken
  1337  		if p.Scond == 0 {
  1338  			*o1 |= 1 << 19
  1339  		}
  1340  
  1341  	// BRZ R, n(PC)
  1342  	case 18:
  1343  		offset := p.Pcond.Pc - p.Pc
  1344  		if offset < -1<<19 || offset > 1<<19-1 {
  1345  			return nil, errors.New("branch target out of range")
  1346  		}
  1347  		if offset%4 != 0 {
  1348  			return nil, errors.New("branch target not mod 4")
  1349  		}
  1350  		*o1 = opcode(p.As) | uint32((offset>>14)&3)<<20 | uint32(p.From.Reg&31)<<14 | uint32(offset>>2)&(1<<14-1)
  1351  		// default is to predict branch taken
  1352  		if p.Scond == 0 {
  1353  			*o1 |= 1 << 19
  1354  		}
  1355  
  1356  	// FBA n(PC)
  1357  	case 19:
  1358  		offset := p.Pcond.Pc - p.Pc
  1359  		if offset < -1<<24 || offset > 1<<24-1 {
  1360  			return nil, errors.New("branch target out of range")
  1361  		}
  1362  		if offset%4 != 0 {
  1363  			return nil, errors.New("branch target not mod 4")
  1364  		}
  1365  		*o1 = opcode(p.As) | uint32(offset>>2)&(1<<22-1)
  1366  
  1367  	// JMPL $imm13(Rs1), Rd
  1368  	case 20:
  1369  		*o1 = opcode(p.As) | rsr(p.From.Reg, p.From.Offset, p.To.Reg)
  1370  
  1371  	// JMPL $(R1+R2), Rd
  1372  	case 21:
  1373  		*o1 = opcode(p.As) | rrr(p.From.Reg, 0, p.From.Index, p.To.Reg)
  1374  
  1375  	// CALL sym(SB)
  1376  	// DUFFCOPY, DUFFZERO
  1377  	case 22:
  1378  		*o1 = opcode(p.As)
  1379  		rel := obj.Addrel(cursym)
  1380  		rel.Off = int32(p.Pc)
  1381  		rel.Siz = 4
  1382  		rel.Sym = p.To.Sym
  1383  		rel.Add = p.To.Offset
  1384  		rel.Type = obj.R_CALLSPARC64
  1385  
  1386  	// MOVD $sym(SB), R ->
  1387  	// 	SETHI hh($sym), TMP
  1388  	// 	OR TMP, hm($sym), TMP
  1389  	//	SLLD	$32, TMP, TMP
  1390  	// 	SETHI hi($sym), R
  1391  	// 	OR R, lo($sym), R
  1392  	// 	OR TMP, R, R
  1393  	case 23:
  1394  		*o1 = opcode(ASETHI) | ir(0, REG_TMP)
  1395  		*o2 = opalu(AOR) | rsr(REG_TMP, 0, REG_TMP)
  1396  		rel := obj.Addrel(cursym)
  1397  		rel.Off = int32(p.Pc)
  1398  		rel.Siz = 8
  1399  		rel.Sym = p.From.Sym
  1400  		rel.Add = p.From.Offset
  1401  		rel.Type = obj.R_ADDRSPARC64HI
  1402  		*o3 = opalu(ASLLD) | rsr(REG_TMP, 32, REG_TMP)
  1403  		*o4 = opcode(ASETHI) | ir(0, p.To.Reg)
  1404  		*o5 = opalu(AOR) | rsr(p.To.Reg, 0, p.To.Reg)
  1405  		rel = obj.Addrel(cursym)
  1406  		rel.Off = int32(p.Pc + 12)
  1407  		rel.Siz = 8
  1408  		rel.Sym = p.From.Sym
  1409  		rel.Add = p.From.Offset
  1410  		rel.Type = obj.R_ADDRSPARC64LO
  1411  		*o6 = opalu(AOR) | rrr(REG_TMP, 0, p.To.Reg, p.To.Reg)
  1412  
  1413  	// MOV sym(SB), R ->
  1414  	// 	SETHI hh($sym), TMP
  1415  	// 	OR TMP, hm($sym), TMP
  1416  	//	SLLD	$32, TMP, TMP
  1417  	// 	SETHI hi($sym), TMP2
  1418  	// 	OR TMP2, lo($sym), TMP2
  1419  	// 	OR TMP, TMP2, TMP2
  1420  	//	MOV (TMP2), R
  1421  	case 24:
  1422  		*o1 = opcode(ASETHI) | ir(0, REG_TMP)
  1423  		*o2 = opalu(AOR) | rsr(REG_TMP, 0, REG_TMP)
  1424  		rel := obj.Addrel(cursym)
  1425  		rel.Off = int32(p.Pc)
  1426  		rel.Siz = 8
  1427  		rel.Sym = p.From.Sym
  1428  		rel.Add = p.From.Offset
  1429  		rel.Type = obj.R_ADDRSPARC64HI
  1430  		*o3 = opalu(ASLLD) | rsr(REG_TMP, 32, REG_TMP)
  1431  		*o4 = opcode(ASETHI) | ir(0, REG_TMP2)
  1432  		*o5 = opalu(AOR) | rsr(REG_TMP2, 0, REG_TMP2)
  1433  		rel = obj.Addrel(cursym)
  1434  		rel.Off = int32(p.Pc + 12)
  1435  		rel.Siz = 8
  1436  		rel.Sym = p.From.Sym
  1437  		rel.Add = p.From.Offset
  1438  		rel.Type = obj.R_ADDRSPARC64LO
  1439  		*o6 = opalu(AOR) | rrr(REG_TMP, 0, REG_TMP2, REG_TMP2)
  1440  		*o7 = opload(p.As) | rsr(REG_TMP2, 0, p.To.Reg)
  1441  
  1442  	// MOV R, sym(SB) ->
  1443  	// 	SETHI hh($sym), TMP
  1444  	// 	OR TMP, hm($sym), TMP
  1445  	//	SLLD	$32, TMP, TMP
  1446  	// 	SETHI hi($sym), TMP2
  1447  	// 	OR TMP2, lo($sym), TMP2
  1448  	// 	OR TMP, TMP2, TMP2
  1449  	//	MOV R, (TMP2)
  1450  	case 25:
  1451  		*o1 = opcode(ASETHI) | ir(0, REG_TMP)
  1452  		*o2 = opalu(AOR) | rsr(REG_TMP, 0, REG_TMP)
  1453  		rel := obj.Addrel(cursym)
  1454  		rel.Off = int32(p.Pc)
  1455  		rel.Siz = 8
  1456  		rel.Sym = p.To.Sym
  1457  		rel.Add = p.To.Offset
  1458  		rel.Type = obj.R_ADDRSPARC64HI
  1459  		*o3 = opalu(ASLLD) | rsr(REG_TMP, 32, REG_TMP)
  1460  		*o4 = opcode(ASETHI) | ir(0, REG_TMP2)
  1461  		*o5 = opalu(AOR) | rsr(REG_TMP2, 0, REG_TMP2)
  1462  		rel = obj.Addrel(cursym)
  1463  		rel.Off = int32(p.Pc + 12)
  1464  		rel.Siz = 8
  1465  		rel.Sym = p.To.Sym
  1466  		rel.Add = p.To.Offset
  1467  		rel.Type = obj.R_ADDRSPARC64LO
  1468  		*o6 = opalu(AOR) | rrr(REG_TMP, 0, REG_TMP2, REG_TMP2)
  1469  		*o7 = opstore(p.As) | rsr(REG_TMP2, 0, p.From.Reg)
  1470  
  1471  	// RET
  1472  	case 26:
  1473  		*o1 = opcode(AJMPL) | rsr(REG_OLR, 8, REG_ZR)
  1474  
  1475  	// TA $tn
  1476  	case 27:
  1477  		if p.From.Offset > 255 {
  1478  			return nil, errors.New("trap number too big")
  1479  		}
  1480  		*o1 = cond(8) | opcode(p.As) | 1<<13 | uint32(p.From.Offset&0xff)
  1481  
  1482  	// MOVD	$imm13(R), Rd -> ADD R, $imm13, Rd
  1483  	case 28:
  1484  		*o1 = opalu(AADD) | rsr(p.From.Reg, p.From.Offset, p.To.Reg)
  1485  
  1486  	// MOVUB Rs, Rd
  1487  	case 29:
  1488  		*o1 = opalu(AAND) | rsr(p.From.Reg, 0xff, p.To.Reg)
  1489  
  1490  	// AMOVUH Rs, Rd
  1491  	case 30:
  1492  		*o1 = opalu(ASLLD) | rsr(p.From.Reg, 48, p.To.Reg)
  1493  		*o2 = opalu(ASRLD) | rsr(p.To.Reg, 48, p.To.Reg)
  1494  
  1495  	// AMOVUW Rs, Rd
  1496  	case 31:
  1497  		*o1 = opalu(ASRLW) | rsr(p.From.Reg, 0, p.To.Reg)
  1498  
  1499  	// AMOVB Rs, Rd
  1500  	case 32:
  1501  		*o1 = opalu(ASLLD) | rsr(p.From.Reg, 56, p.To.Reg)
  1502  		*o2 = opalu(ASRAD) | rsr(p.To.Reg, 56, p.To.Reg)
  1503  
  1504  	// AMOVH Rs, Rd
  1505  	case 33:
  1506  		*o1 = opalu(ASLLD) | rsr(p.From.Reg, 48, p.To.Reg)
  1507  		*o2 = opalu(ASRAD) | rsr(p.To.Reg, 48, p.To.Reg)
  1508  
  1509  	// AMOVW Rs, Rd
  1510  	case 34:
  1511  		*o1 = opalu(ASRAW) | rsr(p.From.Reg, 0, p.To.Reg)
  1512  
  1513  	// ANEG Rs, Rd
  1514  	case 35:
  1515  		*o1 = opalu(ASUB) | rrr(REG_ZR, 0, p.From.Reg, p.To.Reg)
  1516  
  1517  	// CMP R1, R2
  1518  	case 36:
  1519  		*o1 = opalu(ASUBCC) | rrr(p.Reg, 0, p.From.Reg, REG_ZR)
  1520  
  1521  	// CMP $42, R2
  1522  	case 37:
  1523  		*o1 = opalu(ASUBCC) | rsr(p.Reg, p.From.Offset, REG_ZR)
  1524  
  1525  	// BLED, n(PC)
  1526  	// JMP n(PC)
  1527  	case 38:
  1528  		offset := p.Pcond.Pc - p.Pc
  1529  		if offset < -1<<20 || offset > 1<<20-1 {
  1530  			return nil, errors.New("branch target out of range")
  1531  		}
  1532  		if offset%4 != 0 {
  1533  			return nil, errors.New("branch target not mod 4")
  1534  		}
  1535  		*o1 = opcode(p.As) | 2<<20 | uint32(offset>>2)&(1<<19-1)
  1536  		// default is to predict branch taken
  1537  		if p.Scond == 0 {
  1538  			*o1 |= 1 << 19
  1539  		}
  1540  
  1541  	// UNDEF
  1542  	// This is supposed to be something that stops execution.
  1543  	// It's not supposed to be reached, ever, but if it is, we'd
  1544  	// like to be able to tell how we got there.  Assemble as
  1545  	// 0xdead0 which is guaranteed to raise undefined instruction
  1546  	// exception.
  1547  	case 39:
  1548  		*o1 = 0xdead0 // ILLTRAP
  1549  
  1550  	// CALL R
  1551  	// CALL (R)
  1552  	// CALL R, R
  1553  	case 40:
  1554  		*o1 = opcode(AJMPL) | rsr(p.To.Reg, 0, REG_OLR)
  1555  
  1556  	// ADD $huge, Rd
  1557  	// AND $huge, Rs, Rd
  1558  	case 41:
  1559  		move := bigmove(p.Ctxt, &p.From, REG_TMP)
  1560  		*o1, *o2 = move[0], move[1]
  1561  		reg := p.To.Reg
  1562  		if p.Reg != 0 {
  1563  			reg = p.Reg
  1564  		}
  1565  		*o3 = opalu(p.As) | rrr(reg, 0, REG_TMP, p.To.Reg)
  1566  
  1567  	// AMOVD $huge(R), R
  1568  	case 42:
  1569  		move := bigmove(p.Ctxt, &p.From, REG_TMP)
  1570  		*o1, *o2 = move[0], move[1]
  1571  		*o3 = opalu(AADD) | rrr(p.From.Reg, 0, REG_TMP, p.To.Reg)
  1572  
  1573  	// AMOVD R, huge(R)
  1574  	case 43:
  1575  		move := bigmove(p.Ctxt, &p.To, REG_TMP)
  1576  		*o1, *o2 = move[0], move[1]
  1577  		*o3 = opstore(p.As) | rrr(p.To.Reg, 0, REG_TMP, p.From.Reg)
  1578  
  1579  	// AMOVD huge(R), R
  1580  	case 44:
  1581  		move := bigmove(p.Ctxt, &p.From, REG_TMP)
  1582  		*o1, *o2 = move[0], move[1]
  1583  		*o3 = opload(p.As) | rrr(p.From.Reg, 0, REG_TMP, p.To.Reg)
  1584  
  1585  	// JMP sym(SB) ->
  1586  	//	MOVD	$sym(SB), TMP2 ->
  1587  	// 		SETHI hh($sym), TMP
  1588  	// 		OR TMP, hm($sym), TMP
  1589  	//		SLLD	$32, TMP, TMP
  1590  	// 		SETHI hi($sym), TMP2
  1591  	// 		OR TMP2, lo($sym), TMP2
  1592  	// 		OR TMP, TMP2, TMP2
  1593  	//	JMPL	TMP2, ZR
  1594  	case 45:
  1595  		*o1 = opcode(ASETHI) | ir(0, REG_TMP)
  1596  		*o2 = opalu(AOR) | rsr(REG_TMP, 0, REG_TMP)
  1597  		rel := obj.Addrel(cursym)
  1598  		rel.Off = int32(p.Pc)
  1599  		rel.Siz = 8
  1600  		rel.Sym = p.To.Sym
  1601  		rel.Add = p.To.Offset
  1602  		rel.Type = obj.R_ADDRSPARC64HI
  1603  		*o3 = opalu(ASLLD) | rsr(REG_TMP, 32, REG_TMP)
  1604  		*o4 = opcode(ASETHI) | ir(0, REG_TMP2)
  1605  		*o5 = opalu(AOR) | rsr(REG_TMP2, 0, REG_TMP2)
  1606  		rel = obj.Addrel(cursym)
  1607  		rel.Off = int32(p.Pc + 12)
  1608  		rel.Siz = 8
  1609  		rel.Sym = p.To.Sym
  1610  		rel.Add = p.To.Offset
  1611  		rel.Type = obj.R_ADDRSPARC64LO
  1612  		*o6 = opalu(AOR) | rrr(REG_TMP, 0, REG_TMP2, REG_TMP2)
  1613  		*o7 = opcode(AJMPL) | rsr(REG_TMP2, 0, REG_ZR)
  1614  
  1615  	// MOVPOS XCC, $simm11, R
  1616  	case 46:
  1617  		*o1 = opcode(p.As) | rsr(0, p.From3.Offset, p.To.Reg) | 1<<13 | uint32(p.From.Reg&3<<11)
  1618  
  1619  	// MOVPOS ICC, R, R
  1620  	case 47:
  1621  		*o1 = opcode(p.As) | rrr(0, 0, p.Reg, p.To.Reg) | uint32(p.From.Reg&3<<11)
  1622  
  1623  	// MOVRZ	R, $simm10, Rd
  1624  	case 48:
  1625  		*o1 = opcode(p.As) | rsr(p.From.Reg, p.From3.Offset, p.To.Reg) | 1<<13
  1626  
  1627  	// MOVRZ	R, Rs, Rd
  1628  	case 49:
  1629  		*o1 = opcode(p.As) | rrr(p.From.Reg, 0, p.Reg, p.To.Reg)
  1630  
  1631  	// MOVD $tlssym, R
  1632  	case 50:
  1633  		*o1 = opcode(ASETHI) | ir(0, p.To.Reg)
  1634  		*o2 = opalu(AXOR) | rsr(p.To.Reg, 0, p.To.Reg)
  1635  		rel := obj.Addrel(cursym)
  1636  		rel.Off = int32(p.Pc)
  1637  		rel.Siz = 8
  1638  		rel.Sym = p.From.Sym
  1639  		rel.Add = p.From.Offset
  1640  		rel.Type = obj.R_SPARC64_TLS_LE
  1641  		*o3 = opalu(AADD) | rrr(REG_TLS, 0, p.To.Reg, p.To.Reg)
  1642  
  1643  	// RETRESTORE
  1644  	case 51:
  1645  		*o1 = opload(AMOVD) | rsr(REG_RSP, StackBias+120, REG_ILR)
  1646  		*o2 = opcode(AJMPL) | rsr(REG_ILR, 8, REG_ZR)
  1647  		*o3 = opalu(ARESTORE) | rsr(REG_ZR, 0, REG_ZR)
  1648  
  1649  	// JMP $huge(n(PC)) ->
  1650  	//	MOVD	OLR, TMP2
  1651  	//	CALL	+0x4
  1652  	//	MOVD	OLR, TMP
  1653  	//	MOVD	TMP2, OLR
  1654  	//	MOVD	$huge(n(PC)), TMP2
  1655  	//	...
  1656  	//	JMPL	TMP + TMP2
  1657  	case 52:
  1658  		var offset int64
  1659  		if p.Pcond != nil {
  1660  			offset = p.Pcond.Pc - p.Pc
  1661  		} else {
  1662  			// obj.brloop will set p.Pcond to nil for jumps to the same instruction.
  1663  			offset = p.To.Val.(*obj.Prog).Pc - p.Pc
  1664  		}
  1665  
  1666  		branch, err := largebranch(offset)
  1667  		if err != nil {
  1668  			return nil, err
  1669  		}
  1670  		*o1, *o2, *o3, *o4, *o5, *o6, *o7 =
  1671  			branch[0], branch[1], branch[2],
  1672  			branch[3], branch[4], branch[5],
  1673  			branch[6]
  1674  
  1675  	// BLE XCC, $huge(n(PC)) ->
  1676  	//	BLE	XCC, 4(PC)
  1677  	//	NOP
  1678  	//	BA	10(PC)
  1679  	//	NOP
  1680  	//	MOVD	OLR, TMP2
  1681  	//	CALL	+0x4
  1682  	//	MOVD	OLR, TMP
  1683  	//	MOVD	TMP2, OLR
  1684  	//	MOVD	$huge(n(PC)), TMP2
  1685  	//	...
  1686  	//	JMP	TMP + TMP2
  1687  	//	NOP
  1688  	case 53:
  1689  		offset := int64(16)
  1690  		*o1 = opcode(p.As) | uint32(p.From.Reg&3)<<20 | uint32(offset>>2)&(1<<19-1)
  1691  		// default is to predict branch taken
  1692  		if p.Scond == 0 {
  1693  			*o1 |= 1 << 19
  1694  		}
  1695  
  1696  		if p.Pcond != nil {
  1697  			offset = p.Pcond.Pc - p.Pc
  1698  		} else {
  1699  			// obj.brloop will set p.Pcond to nil for jumps to the same instruction.
  1700  			offset = p.To.Val.(*obj.Prog).Pc - p.Pc
  1701  		}
  1702  		*o2 = opcode(ARNOP)
  1703  		*o3 = opcode(obj.AJMP) | uint32(10)&(1<<22-1)
  1704  		*o4 = opcode(ARNOP)
  1705  
  1706  		offset = p.Pcond.Pc - p.Pc
  1707  		offset -= 16 // make branch relative to first instruction
  1708  		branch, err := largebranch(offset)
  1709  		if err != nil {
  1710  			return nil, err
  1711  		}
  1712  		*o5, *o6, *o7, *o8, *o9, *o10, *o11 =
  1713  			branch[0], branch[1], branch[2],
  1714  			branch[3], branch[4], branch[5],
  1715  			branch[6]
  1716  		*o12 = opcode(ARNOP)
  1717  
  1718  	// BRZ R, $huge(n(PC)) ->
  1719  	//	BRZ	R, 4(PC)
  1720  	//	NOP
  1721  	//	BA	10(PC)
  1722  	//	NOP
  1723  	//	MOVD	OLR, TMP2
  1724  	//	CALL	+0x4
  1725  	//	MOVD	OLR, TMP
  1726  	//	MOVD	TMP2, OLR
  1727  	//	MOVD	$huge(n(PC)), TMP2
  1728  	//	...
  1729  	//	JMP	TMP + TMP2
  1730  	//	NOP
  1731  	case 54:
  1732  		offset := int64(16)
  1733  		*o1 = opcode(p.As) | uint32((offset>>14)&3)<<20 | uint32(p.From.Reg&31)<<14 | uint32(offset>>2)&(1<<14-1)
  1734  		// default is to predict branch taken
  1735  		if p.Scond == 0 {
  1736  			*o1 |= 1 << 19
  1737  		}
  1738  		*o2 = opcode(ARNOP)
  1739  		*o3 = opcode(obj.AJMP) | uint32(10)&(1<<22-1)
  1740  		*o4 = opcode(ARNOP)
  1741  
  1742  		offset = p.Pcond.Pc - p.Pc
  1743  		offset -= 16 // make branch relative to first instruction
  1744  		branch, err := largebranch(offset)
  1745  		if err != nil {
  1746  			return nil, err
  1747  		}
  1748  		*o5, *o6, *o7, *o8, *o9, *o10, *o11 =
  1749  			branch[0], branch[1], branch[2],
  1750  			branch[3], branch[4], branch[5],
  1751  			branch[6]
  1752  		*o12 = opcode(ARNOP)
  1753  
  1754  	// FBA $huge(n(PC)) ->
  1755  	//	FBA	4(PC)
  1756  	//	NOP
  1757  	//	BA	10(PC)
  1758  	//	NOP
  1759  	//	MOVD	OLR, TMP2
  1760  	//	CALL	+0x4
  1761  	//	MOVD	OLR, TMP
  1762  	//	MOVD	TMP2, OLR
  1763  	//	MOVD	$huge(n(PC)), TMP2
  1764  	//	...
  1765  	//	JMP	TMP + TMP2
  1766  	//	NOP
  1767  	case 55:
  1768  		offset := int64(16)
  1769  		*o1 = opcode(p.As) | uint32(offset>>2)&(1<<22-1)
  1770  		*o2 = opcode(ARNOP)
  1771  		*o3 = opcode(obj.AJMP) | uint32(10)&(1<<22-1)
  1772  		*o4 = opcode(ARNOP)
  1773  
  1774  		offset = p.Pcond.Pc - p.Pc
  1775  		offset -= 16 // make branch relative to first instruction
  1776  		branch, err := largebranch(offset)
  1777  		if err != nil {
  1778  			return nil, err
  1779  		}
  1780  		*o5, *o6, *o7, *o8, *o9, *o10, *o11 =
  1781  			branch[0], branch[1], branch[2],
  1782  			branch[3], branch[4], branch[5],
  1783  			branch[6]
  1784  		*o12 = opcode(ARNOP)
  1785  
  1786  	// BLED, $huge(n(PC)) ->
  1787  	//	BLED, 4(PC)
  1788  	//	NOP
  1789  	//	BA	10(PC)
  1790  	//	NOP
  1791  	//	MOVD	OLR, TMP2
  1792  	//	CALL	+0x4
  1793  	//	MOVD	OLR, TMP
  1794  	//	MOVD	TMP2, OLR
  1795  	//	MOVD	$huge(n(PC)), TMP2
  1796  	//	...
  1797  	//	JMP	TMP + TMP2
  1798  	//	NOP
  1799  	case 56:
  1800  		offset := int64(16)
  1801  		*o1 = opcode(p.As) | 2<<20 | uint32(offset>>2)&(1<<19-1)
  1802  		// default is to predict branch taken
  1803  		if p.Scond == 0 {
  1804  			*o1 |= 1 << 19
  1805  		}
  1806  		*o2 = opcode(ARNOP)
  1807  		*o3 = opcode(obj.AJMP) | uint32(10)&(1<<22-1)
  1808  		*o4 = opcode(ARNOP)
  1809  
  1810  		offset = p.Pcond.Pc - p.Pc
  1811  		offset -= 16 // make branch relative to first instruction
  1812  		branch, err := largebranch(offset)
  1813  		if err != nil {
  1814  			return nil, err
  1815  		}
  1816  		*o5, *o6, *o7, *o8, *o9, *o10, *o11 =
  1817  			branch[0], branch[1], branch[2],
  1818  			branch[3], branch[4], branch[5],
  1819  			branch[6]
  1820  		*o12 = opcode(ARNOP)
  1821  
  1822  	// CALL n(PC)
  1823  	// CALL $huge(n(PC))
  1824  	case 57:
  1825  		var offset int64
  1826  		if p.Pcond != nil {
  1827  			offset = p.Pcond.Pc - p.Pc
  1828  		} else {
  1829  			// obj.brloop will set p.Pcond to nil for jumps to the same instruction.
  1830  			offset = p.To.Val.(*obj.Prog).Pc - p.Pc
  1831  		}
  1832  		if offset < -1<<31 || offset > 1<<31-4 {
  1833  			return nil, errors.New("branch target out of range")
  1834  		}
  1835  		if offset%4 != 0 {
  1836  			return nil, errors.New("branch target not mod 4")
  1837  		}
  1838  		*o1 = opcode(obj.ACALL) | d30(int(offset>>2))
  1839  	}
  1840  
  1841  	return out[:o.size/4], nil
  1842  }