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 }