001/* 002 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.asm.sparc; 024 025import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.*; 026import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.*; 027import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.*; 028import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.*; 029import static com.oracle.graal.asm.sparc.SPARCAssembler.Ops.*; 030import static java.lang.String.*; 031import static jdk.internal.jvmci.sparc.SPARC.*; 032 033import java.util.*; 034 035import jdk.internal.jvmci.code.*; 036import jdk.internal.jvmci.meta.*; 037import jdk.internal.jvmci.sparc.*; 038import jdk.internal.jvmci.sparc.SPARC.CPUFeature; 039 040import com.oracle.graal.asm.*; 041 042/** 043 * This class implements an assembler that can encode most SPARC instructions. 044 */ 045public abstract class SPARCAssembler extends Assembler { 046 047 /** 048 * Constructs an assembler for the SPARC architecture. 049 * 050 * @param registerConfig the register configuration used to bind {@link Register#Frame} and 051 * {@link Register#CallerFrame} to physical registers. This value can be null if this 052 * assembler instance will not be used to assemble instructions using these logical 053 * registers. 054 */ 055 public SPARCAssembler(TargetDescription target, RegisterConfig registerConfig) { 056 super(target); 057 } 058 059 public static final int CCR_ICC_SHIFT = 0; 060 public static final int CCR_XCC_SHIFT = 4; 061 public static final int CCR_V_SHIFT = 1; 062 063 protected static final int OP2_SHIFT = 22; 064 protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000; 065 066 protected static final int DISP22_SHIFT = 0; 067 protected static final int DISP22_MASK = 0b00000000001111111111111111111111; 068 069 protected static final int DISP19_SHIFT = 0; 070 protected static final int DISP19_MASK = 0b00000000000001111111111111111111; 071 072 protected static final int D16HI_SHIFT = 20; 073 protected static final int D16HI_MASK = 0b0000_0000_0011_0000_0000_0000_0000_0000; 074 protected static final int D16LO_SHIFT = 0; 075 protected static final int D16LO_MASK = 0b0000_0000_0000_0000_0011_1111_1111_1111; 076 077 protected static final int D10LO_MASK = 0b0000_0000_0000_0000_0001_1111_1110_0000; 078 protected static final int D10HI_MASK = 0b0000_0000_0001_1000_0000_0000_0000_0000; 079 protected static final int D10LO_SHIFT = 5; 080 protected static final int D10HI_SHIFT = 19; 081 082 private static final Ops[] OPS; 083 private static final Op2s[] OP2S; 084 private static final Op3s[][] OP3S; 085 086 private ArrayList<Integer> delaySlotOptimizationPoints = new ArrayList<>(5); 087 088 static { 089 Ops[] ops = Ops.values(); 090 OPS = new Ops[ops.length]; 091 for (Ops op : ops) { 092 OPS[op.value] = op; 093 } 094 Op2s[] op2s = Op2s.values(); 095 OP2S = new Op2s[op2s.length]; 096 for (Op2s op2 : op2s) { 097 OP2S[op2.value] = op2; 098 } 099 OP3S = new Op3s[2][64]; 100 for (Op3s op3 : Op3s.values()) { 101 if (op3.value >= 1 << 6) { 102 throw new RuntimeException("Error " + op3 + " " + op3.value); 103 } 104 OP3S[op3.op.value & 1][op3.value] = op3; 105 } 106 } 107 108 public enum Ops { 109 // @formatter:off 110 111 BranchOp(0b00), 112 CallOp(0b01), 113 ArithOp(0b10), 114 LdstOp(0b11); 115 116 // @formatter:on 117 118 private final int value; 119 120 private Ops(int value) { 121 this.value = value; 122 } 123 124 public int getValue() { 125 return value; 126 } 127 128 public boolean appliesTo(int instructionWord) { 129 int opShift = 30; 130 return (instructionWord >>> opShift) == value; 131 } 132 } 133 134 public enum Op2s { 135 // @formatter:off 136 137 Illtrap(0b000), 138 Bpr (0b011), 139 Fb (0b110), 140 Fbp (0b101), 141 Br (0b010), 142 Bp (0b001), 143 Cb (0b111), 144 Sethi (0b100); 145 146 147 // @formatter:on 148 149 private final int value; 150 151 private Op2s(int value) { 152 this.value = value; 153 } 154 155 public int getValue() { 156 return value; 157 } 158 159 public static Op2s byValue(int value) { 160 return OP2S[value]; 161 } 162 } 163 164 public enum Op3s { 165 // @formatter:off 166 167 Add(0x00, "add", ArithOp), 168 And(0x01, "and", ArithOp), 169 Or(0x02, "or", ArithOp), 170 Xor(0x03, "xor", ArithOp), 171 Sub(0x04, "sub", ArithOp), 172 Andn(0x05, "andn", ArithOp), 173 Orn(0x06, "orn", ArithOp), 174 Xnor(0x07, "xnor", ArithOp), 175 Addc(0x08, "addc", ArithOp), 176 Mulx(0x09, "mulx", ArithOp), 177 Umul(0x0A, "umul", ArithOp), 178 Smul(0x0B, "smul", ArithOp), 179 Subc(0x0C, "subc", ArithOp), 180 Udivx(0x0D, "udivx", ArithOp), 181 Udiv(0x0E, "udiv", ArithOp), 182 Sdiv(0x0F, "sdiv", ArithOp), 183 184 Addcc(0x10, "addcc", ArithOp), 185 Andcc(0x11, "andcc", ArithOp), 186 Orcc(0x12, "orcc", ArithOp), 187 Xorcc(0x13, "xorcc", ArithOp), 188 Subcc(0x14, "subcc", ArithOp), 189 Andncc(0x15, "andncc", ArithOp), 190 Orncc(0x16, "orncc", ArithOp), 191 Xnorcc(0x17, "xnorcc", ArithOp), 192 Addccc(0x18, "addccc", ArithOp), 193 194 Umulcc(0x1A, "umulcc", ArithOp), 195 Smulcc(0x1B, "smulcc", ArithOp), 196 Subccc(0x1C, "subccc", ArithOp), 197 Udivcc(0x1E, "udivcc", ArithOp), 198 Sdivcc(0x1F, "sdivcc", ArithOp), 199 200 Taddcc(0x20, "taddcc", ArithOp), 201 Tsubcc(0x21, "tsubcc", ArithOp), 202 Taddcctv(0x22, "taddcctv", ArithOp), 203 Tsubcctv(0x23, "tsubcctv", ArithOp), 204 Mulscc(0x24, "mulscc", ArithOp), 205 Sll(0x25, "sll", ArithOp), 206 Sllx(0x25, "sllx", ArithOp), 207 Srl(0x26, "srl", ArithOp), 208 Srlx(0x26, "srlx", ArithOp), 209 Sra(0x27, "srax", ArithOp), 210 Srax(0x27, "srax", ArithOp), 211 Membar(0x28, "membar", ArithOp), 212 213 Flushw(0x2B, "flushw", ArithOp), 214 Movcc(0x2C, "movcc", ArithOp), 215 Sdivx(0x2D, "sdivx", ArithOp), 216 Popc(0x2E, "popc", ArithOp), 217 Movr(0x2F, "movr", ArithOp), 218 219 Fpop1(0b11_0100, "fpop1", ArithOp), 220 Fpop2(0b11_0101, "fpop2", ArithOp), 221 Impdep1(0b11_0110, "impdep1", ArithOp), 222 Impdep2(0b11_0111, "impdep2", ArithOp), 223 Jmpl(0x38, "jmpl", ArithOp), 224 Rett(0x39, "rett", ArithOp), 225 Trap(0x3a, "trap", ArithOp), 226 Flush(0x3b, "flush", ArithOp), 227 Save(0x3c, "save", ArithOp), 228 Restore(0x3d, "restore", ArithOp), 229 Retry(0x3e, "retry", ArithOp), 230 231 232 Casa(0b111100, "casa", LdstOp), 233 Casxa(0b111110, "casxa", LdstOp), 234 Prefetch(0b101101, "prefetch", LdstOp), 235 Prefetcha(0b111101, "prefetcha", LdstOp), 236 237 Lduw (0b00_0000, "lduw", LdstOp), 238 Ldub (0b00_0001, "ldub", LdstOp), 239 Lduh (0b00_0010, "lduh", LdstOp), 240 Stw (0b00_0100, "stw", LdstOp), 241 Stb (0b00_0101, "stb", LdstOp), 242 Sth (0b00_0110, "sth", LdstOp), 243 Ldsw (0b00_1000, "ldsw", LdstOp), 244 Ldsb (0b00_1001, "ldsb", LdstOp), 245 Ldsh (0b00_1010, "ldsh", LdstOp), 246 Ldx (0b00_1011, "ldx", LdstOp), 247 Stx (0b00_1110, "stx", LdstOp), 248 249 Ldf (0b10_0000, "ldf", LdstOp), 250 Ldfsr (0b10_0001, "ldfsr", LdstOp), 251 Ldaf (0b10_0010, "ldaf", LdstOp), 252 Lddf (0b10_0011, "lddf", LdstOp), 253 Stf (0b10_0100, "stf", LdstOp), 254 Stfsr (0b10_0101, "stfsr", LdstOp), 255 Staf (0b10_0110, "staf", LdstOp), 256 Stdf (0b10_0111, "stdf", LdstOp), 257 258 Rd (0b10_1000, "rd", ArithOp), 259 Wr (0b11_0000, "wr", ArithOp), 260 Fcmp (0b11_0101, "fcmp", ArithOp), 261 262 Ldxa (0b01_1011, "ldxa", LdstOp), 263 Lduwa (0b01_0000, "lduwa", LdstOp), 264 265 Tcc(0b11_1010, "tcc", ArithOp); 266 267 // @formatter:on 268 269 private final int value; 270 private final String operator; 271 private final Ops op; 272 273 private Op3s(int value, String name, Ops op) { 274 assert isImm(value, 6); 275 this.value = value; 276 this.operator = name; 277 this.op = op; 278 } 279 280 public int getValue() { 281 return value; 282 } 283 284 public String getOperator() { 285 return operator; 286 } 287 288 public boolean throwsException() { 289 if (op == LdstOp) { 290 return true; 291 } 292 switch (this) { 293 case Udiv: 294 case Udivx: 295 case Sdiv: 296 case Sdivx: 297 case Udivcc: 298 case Sdivcc: 299 return true; 300 default: 301 return false; 302 } 303 } 304 } 305 306 public enum Opfs { 307 // @formatter:off 308 309 Fmovs(0b0_0000_0001, "fmovs"), 310 Fmovd(0b0_0000_0010, "fmovd"), 311 Fmovq(0b0_0000_0011, "fmovq"), 312 Fmovscc(0b00_0001, "fmovscc"), 313 Fmovdcc(0b00_0010, "fmovdcc"), 314 Fnegs(0x05, "fnegs"), 315 Fnegd(0x06, "fnegd"), 316 Fnegq(0x07, "fnegq"), 317 Fabss(0x09, "fabss"), 318 Fabsd(0x0A, "fabsd"), 319 Fabsq(0x0B, "fabsq"), 320 321 // start VIS1 322 Edge8cc(0x0, "edge8cc"), 323 Edge8n(0x1, "edge8n"), 324 Edge8lcc(0x2, "edge8lcc"), 325 Edge8ln(0x3, "edge8ln"), 326 Edge16cc(0x4, "edge16cc"), 327 Edge16n(0x5, "edge16n"), 328 Edge16lcc(0x6, "edge16lcc"), 329 Edge16ln(0x7, "edge16ln"), 330 Edge32cc(0x8, "edge32cc"), 331 Edge32n(0x9, "edge32n"), 332 Edge32lcc(0xA, "edge32lcc"), 333 Edge32ln(0xB, "edge32ln"), 334 Array8(0x10, "array8"), 335 Array16(0x12, "array16"), 336 Array32(0x14, "array32"), 337 AlignAddress(0x18, "alignaddress"), 338 AlignAddressLittle(0x1A, "alignaddress_little"), 339 Fpcmple16(0x20, "fpcmple16"), 340 Fpcmpne16(0x22, "fpcmpne16"), 341 Fpcmple32(0x24, "fpcmple32"), 342 Fpcmpne32(0x26, "fpcmpne32"), 343 Fpcmpgt16(0x28, "fpcmpgt16"), 344 Fpcmpeq16(0x2A, "fpcmpeq16"), 345 Fpcmpgt32(0x2C, "fpcmpgt32"), 346 Fpcmpeq32(0x2E, "fpcmpeq32"), 347 Fmul8x16(0x31, "fmul8x16"), 348 Fmul8x16au(0x33, "fmul8x16au"), 349 Fmul8x16al(0x35, "fmul8x16al"), 350 Fmul8sux16(0x36, "fmul8sux16"), 351 Fmul8ulx16(0x37, "fmul8ulx16"), 352 Fmuld8sux16(0x38, "fmuld8sux16"), 353 Fmuld8ulx16(0x39, "fmuld8ulx16"), 354 Fpack32(0x3A, "fpack32"), 355 Fpack16(0x3B, "fpack16"), 356 Fpackfix(0x3D, "fpackfix"), 357 Faligndatag(0x48, "faligndata"), 358 Fpmerge(0x4B, "fpmerge"), 359 Fpadd16(0x50, "fpadd16"), 360 Fpadd16s(0x51, "fpadd16s"), 361 Fpadd32(0x52, "fpadd32"), 362 Fpadd32s(0x53, "fpadd32s"), 363 Fpsub16(0x54, "fpadd16"), 364 Fpsub16s(0x55, "fpadd16s"), 365 Fpsub32(0x56, "fpadd32"), 366 Fpsub32s(0x57, "fpadd32s"), 367 Fzerod(0x60, "fzerod"), 368 Fzeros(0x61, "fzeros"), 369 Fnot2d(0x66, "fnot1d"), 370 Fnot2s(0x67, "fnot1s"), 371 Fnot1d(0x6A, "fnot1d"), 372 Fnot1s(0x6B, "fnot1s"), 373 Fsrc1d(0x74, "fsrc1d"), 374 Fsrc1s(0x75, "fsrc1s"), 375 Fsrc2d(0x78, "fsrc2d"), 376 Fsrc2s(0x79, "fsrc2s"), 377 Foned(0x7E, "foned"), 378 Fones(0x7F, "fones"), 379 Fandd(0b0_0111_0000, "fandd"), 380 Fands(0b0_0111_0001, "fands"), 381 Fxord(0b0_0110_1100, "fxord"), 382 Fxors(0b0_0110_1101, "fxors"), 383 // end VIS1 384 385 // start VIS2 386 Bmask(0x19, "bmask"), 387 Bshuffle(0x4c, "bshuffle"), 388 // end VIS2 only 389 390 // start VIS3 391 Addxc(0x11, "addxc"), 392 Addxccc(0x13, "addxccc"), 393 Cmask8(0x1B, "cmask8"), 394 Cmask16(0x1D, "cmask16"), 395 Cmask32(0x1F, "cmask32"), 396 Fmean16(0x40, "fmean16"), 397 Fnadds(0x51, "fnadds"), 398 Fnaddd(0x52, "fnaddd"), 399 Fnmuls(0x59, "fnmuls"), 400 Fnmuld(0x5A, "fnmuld"), 401 Fnsmuld(0x79, "fnsmuld"), 402 Fnhadds(0x71, "fnhadds"), 403 Fnhaddd(0x72, "fnhaddd"), 404 Movdtox(0x110, "movdtox"), 405 Movstouw(0x111, "movstouw"), 406 Movstosw(0x113, "movstosw"), 407 Movxtod(0x118, "movxtod"), 408 Movwtos(0b1_0001_1001, "movwtos"), 409 UMulxhi(0b0_0001_0110, "umulxhi"), 410 Lzcnt (0b0_0001_0111, "lzcnt"), 411 // end VIS3 412 413 // start CAMMELLIA 414 CammelliaFl(0x13C, "cammelia_fl"), 415 CammelliaFli(0x13D, "cammellia_fli"), 416 // end CAMMELLIA 417 418 // start CRYPTO 419 Crc32c(0x147, "crc32c"), 420 // end CRYPTO 421 422 // start OSA 2011 423 Fpadd64(0x44, "fpadd64"), 424 Fpsub64(0x46, "fpsub64"), 425 Fpadds16(0x58, "fpadds16"), 426 Fpadds16s(0x59, "fpadds16"), 427 Fpadds32(0x5A, "fpadds32"), 428 Fpadds32s(0x5B, "fpadds32s"), 429 Fpsubs16(0x5C, "fpsubs16"), 430 Fpsubs16s(0x5D, "fpsubs16s"), 431 Fpsubs32(0x5E, "fpsubs32"), 432 Fpsubs32s(0x5F, "fpsubs32s"), 433 Fpcmpne8(0x122, "fpcmpne8"), 434 Fpcmpeq8(0x12C, "fpcmpeq8"), 435 // end OSA 2011 436 437 Fadds(0x41, "fadds"), 438 Faddd(0x42, "faddd"), 439 Faddq(0x43, "faddq"), 440 Fsubs(0x45, "fsubs"), 441 Fsubd(0x46, "fsubd"), 442 Fsubq(0x47, "fsubq"), 443 Fmuls(0x49, "fmuls"), 444 Fmuld(0x4A, "fmuld"), 445 Fdivs(0x4D, "fdivs"), 446 Fdivd(0x4E, "fdivd"), 447 Fdivq(0x4F, "fdivq"), 448 449 Fsqrts(0x29, "fsqrts"), 450 Fsqrtd(0x2A, "fsqrtd"), 451 Fsqrtq(0x2B, "fsqrtq"), 452 453 Fsmuld(0x69, "fsmuld"), 454 Fmulq(0x6B, "fmulq"), 455 Fdmuldq(0x6E, "fdmulq"), 456 457 Fstoi(0xD1, "fstoi"), 458 Fdtoi(0xD2, "fdtoi"), 459 Fstox(0x81, "fstox"), 460 Fdtox(0x82, "fdtox"), 461 Fxtos(0x84, "fxtos"), 462 Fxtod(0x88, "fxtod"), 463 Fxtoq(0x8C, "fxtoq"), 464 Fitos(0xC4, "fitos"), 465 Fdtos(0xC6, "fdtos"), 466 Fitod(0xC8, "fitod"), 467 Fstod(0xC9, "fstod"), 468 Fitoq(0xCC, "fitoq"), 469 470 471 Fcmps(0x51, "fcmps"), 472 Fcmpd(0x52, "fcmpd"), 473 Fcmpq(0x53, "fcmpq"); 474 475 // @formatter:on 476 477 private final int value; 478 private final String operator; 479 480 private Opfs(int value, String op) { 481 this.value = value; 482 this.operator = op; 483 } 484 485 public int getValue() { 486 return value; 487 } 488 489 public String getOperator() { 490 return operator; 491 } 492 } 493 494 public enum Annul { 495 ANNUL(1), 496 NOT_ANNUL(0); 497 public final int flag; 498 499 Annul(int flag) { 500 this.flag = flag; 501 } 502 } 503 504 public enum BranchPredict { 505 PREDICT_TAKEN(1), 506 PREDICT_NOT_TAKEN(0); 507 public final int flag; 508 509 BranchPredict(int flag) { 510 this.flag = flag; 511 } 512 } 513 514 public enum MembarMask { 515 // @formatter:off 516 517 StoreStore(1 << 3, "storestore"), 518 LoadStore(1 << 2, "loadstore"), 519 StoreLoad(1 << 1, "storeload"), 520 LoadLoad(1 << 0, "loadload"), 521 Sync(1 << 6, "sync"), 522 MemIssue(1 << 5, "memissue"), 523 LookAside(1 << 4, "lookaside"); 524 525 // @formatter:on 526 527 private final int value; 528 private final String operator; 529 530 private MembarMask(int value, String op) { 531 this.value = value; 532 this.operator = op; 533 } 534 535 public int getValue() { 536 return value | 0x2000; 537 } 538 539 public String getOperator() { 540 return operator; 541 } 542 } 543 544 /** 545 * Condition Codes to use for instruction. 546 */ 547 public enum CC { 548 // @formatter:off 549 /** 550 * Condition is considered as 32bit operation condition. 551 */ 552 Icc(0b00, "icc", false), 553 /** 554 * Condition is considered as 64bit operation condition. 555 */ 556 Xcc(0b10, "xcc", false), 557 Fcc0(0b00, "fcc0", true), 558 Fcc1(0b01, "fcc1", true), 559 Fcc2(0b10, "fcc2", true), 560 Fcc3(0b11, "fcc3", true); 561 562 // @formatter:on 563 564 private final int value; 565 private final String operator; 566 private boolean isFloat; 567 568 private CC(int value, String op, boolean isFloat) { 569 this.value = value; 570 this.operator = op; 571 this.isFloat = isFloat; 572 } 573 574 public int getValue() { 575 return value; 576 } 577 578 public String getOperator() { 579 return operator; 580 } 581 582 public static CC forKind(Kind kind) { 583 boolean isInt = kind == Kind.Boolean || kind == Kind.Byte || kind == Kind.Char || kind == Kind.Short || kind == Kind.Int; 584 boolean isFloat = kind == Kind.Float || kind == Kind.Double; 585 boolean isLong = kind == Kind.Long || kind == Kind.Object; 586 assert isInt || isFloat || isLong; 587 if (isLong) { 588 return Xcc; 589 } else if (isInt) { 590 return Icc; 591 } else if (isFloat) { 592 return Fcc0; 593 } else { 594 throw new InternalError(); 595 } 596 } 597 } 598 599 public enum ConditionFlag { 600 // @formatter:off 601 602 // for FBfcc & FBPfcc instruction 603 F_Never(0, "f_never"), 604 F_NotEqual(1, "f_notEqual"), 605 F_LessOrGreater(2, "f_lessOrGreater"), 606 F_UnorderedOrLess(3, "f_unorderedOrLess"), 607 F_Less(4, "f_less"), 608 F_UnorderedOrGreater(5, "f_unorderedOrGreater"), 609 F_Greater(6, "f_greater"), 610 F_Unordered(7, "f_unordered"), 611 F_Always(8, "f_always"), 612 F_Equal(9, "f_equal"), 613 F_UnorderedOrEqual(10, "f_unorderedOrEqual"), 614 F_GreaterOrEqual(11, "f_greaterOrEqual"), 615 F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"), 616 F_LessOrEqual(13, "f_lessOrEqual"), 617 F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"), 618 F_Ordered(15, "f_ordered"), 619 620 // for integers 621 Never(0, "never"), 622 Equal(1, "equal", true), 623 Zero(1, "zero"), 624 LessEqual(2, "lessEqual", true), 625 Less(3, "less", true), 626 LessEqualUnsigned(4, "lessEqualUnsigned", true), 627 LessUnsigned(5, "lessUnsigned", true), 628 CarrySet(5, "carrySet"), 629 Negative(6, "negative", true), 630 OverflowSet(7, "overflowSet", true), 631 Always(8, "always"), 632 NotEqual(9, "notEqual", true), 633 NotZero(9, "notZero"), 634 Greater(10, "greater", true), 635 GreaterEqual(11, "greaterEqual", true), 636 GreaterUnsigned(12, "greaterUnsigned", true), 637 GreaterEqualUnsigned(13, "greaterEqualUnsigned", true), 638 CarryClear(13, "carryClear"), 639 Positive(14, "positive", true), 640 OverflowClear(15, "overflowClear", true); 641 642 // @formatter:on 643 644 private final int value; 645 private final String operator; 646 private boolean forCBcond = false; 647 648 private ConditionFlag(int value, String op) { 649 this(value, op, false); 650 } 651 652 private ConditionFlag(int value, String op, boolean cbcond) { 653 this.value = value; 654 this.operator = op; 655 this.forCBcond = cbcond; 656 } 657 658 public boolean isCBCond() { 659 return forCBcond; 660 } 661 662 public int getValue() { 663 return value; 664 } 665 666 public String getOperator() { 667 return operator; 668 } 669 670 public ConditionFlag negate() { 671 //@formatter:off 672 switch (this) { 673 case F_Never : return F_Always; 674 case F_Always : return F_Never; 675 case F_NotEqual : return F_Equal; 676 case F_Equal : return F_NotEqual; 677 case F_LessOrGreater : return F_UnorderedOrEqual; 678 case F_UnorderedOrEqual : return F_LessOrGreater; 679 case F_Less : return F_UnorderedGreaterOrEqual; 680 case F_UnorderedGreaterOrEqual: return F_Less; 681 case F_LessOrEqual : return F_UnorderedOrGreater; 682 case F_UnorderedOrGreater : return F_LessOrEqual; 683 case F_Greater : return F_UnorderedOrLessOrEqual; 684 case F_UnorderedOrLessOrEqual : return F_Greater; 685 case F_GreaterOrEqual : return F_UnorderedOrLess; 686 case F_UnorderedOrLess : return F_GreaterOrEqual; 687 case F_Unordered : return F_Ordered; 688 case F_Ordered : return F_Unordered; 689 case Never : return Always; 690 case Always : return Never; 691 case Equal : return NotEqual; 692 case NotEqual : return Equal; 693 case Zero : return NotZero; 694 case NotZero : return Zero; 695 case LessEqual : return Greater; 696 case Greater : return LessEqual; 697 case Less : return GreaterEqual; 698 case GreaterEqual : return Less; 699 case LessEqualUnsigned : return GreaterUnsigned; 700 case GreaterUnsigned : return LessEqualUnsigned; 701 case LessUnsigned : return GreaterEqualUnsigned; 702 case GreaterEqualUnsigned : return LessUnsigned; 703 case CarrySet : return CarryClear; 704 case CarryClear : return CarrySet; 705 case Negative : return Positive; 706 case Positive : return Negative; 707 case OverflowSet : return OverflowClear; 708 case OverflowClear : return OverflowSet; 709 default: 710 throw new InternalError(); 711 } 712 //@formatter:on 713 } 714 715 public ConditionFlag mirror() { 716 switch (this) { 717 //@formatter:off 718 case F_Less : return F_Greater; 719 case F_Greater : return F_Less; 720 case F_LessOrEqual : return F_GreaterOrEqual; 721 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual; 722 case F_UnorderedOrGreater : return F_UnorderedOrLess; 723 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual; 724 case F_GreaterOrEqual : return F_LessOrEqual; 725 case F_UnorderedOrLess : return F_UnorderedOrGreater; 726 case LessEqual : return GreaterEqual; 727 case Greater : return Less; 728 case Less : return Greater; 729 case GreaterEqual : return LessEqual; 730 case LessEqualUnsigned : return GreaterEqualUnsigned; 731 case GreaterUnsigned : return LessUnsigned; 732 case LessUnsigned : return GreaterUnsigned; 733 case GreaterEqualUnsigned : return LessEqualUnsigned; 734 default: 735 return this; 736 //@formatter:on 737 } 738 } 739 740 } 741 742 public enum RCondition { 743 // @formatter:off 744 745 Rc_z(0b001, "rc_z"), 746 Rc_lez(0b010, "rc_lez"), 747 Rc_lz(0b011, "rc_lz"), 748 Rc_nz(0b101, "rc_nz"), 749 Rc_gz(0b110, "rc_gz"), 750 Rc_gez(0b111, "rc_gez"), 751 Rc_last(Rc_gez.getValue(), "rc_last"); 752 753 // @formatter:on 754 755 private final int value; 756 private final String operator; 757 758 private RCondition(int value, String op) { 759 this.value = value; 760 this.operator = op; 761 } 762 763 public int getValue() { 764 return value; 765 } 766 767 public String getOperator() { 768 return operator; 769 } 770 } 771 772 /** 773 * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture. 774 */ 775 public enum Asi { 776 // @formatter:off 777 778 INVALID(-1), 779 ASI_PRIMARY(0x80), 780 ASI_PRIMARY_NOFAULT(0x82), 781 ASI_PRIMARY_LITTLE(0x88), 782 // Block initializing store 783 ASI_ST_BLKINIT_PRIMARY(0xE2), 784 // Most-Recently-Used (MRU) BIS variant 785 ASI_ST_BLKINIT_MRU_PRIMARY(0xF2); 786 787 // @formatter:on 788 789 private final int value; 790 791 private Asi(int value) { 792 this.value = value; 793 } 794 795 public int getValue() { 796 return value; 797 } 798 799 public boolean isValid() { 800 return value != INVALID.getValue(); 801 } 802 } 803 804 public enum Fcn { 805 SeveralWritesAndPossiblyReads(2), 806 SeveralReadsWeak(0), 807 OneRead(1), 808 OneWrite(3), 809 Page(4), 810 NearestUnifiedCache(17), 811 SeveralReadsStrong(20), 812 OneReadStrong(21), 813 SeveralWritesAndPossiblyReadsStrong(22), 814 OneWriteStrong(23); 815 816 private final int value; 817 818 private Fcn(int value) { 819 this.value = value; 820 } 821 822 public int getValue() { 823 return value; 824 } 825 } 826 827 /** 828 * Specifies various bit fields used in SPARC instructions. 829 */ 830 @SuppressWarnings("unused") 831 public abstract static class BitSpec { 832 private static final BitSpec op = new ContinousBitSpec(31, 30, "op"); 833 private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2"); 834 private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3"); 835 private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd"); 836 private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1"); 837 private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2"); 838 private static final BitSpec simm13 = new ContinousBitSpec(12, 0, "simm13"); 839 private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22"); 840 private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI"); 841 private static final BitSpec i = new ContinousBitSpec(13, 13, "i"); 842 private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19"); 843 private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22"); 844 private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30"); 845 private static final BitSpec a = new ContinousBitSpec(29, 29, "a"); 846 private static final BitSpec p = new ContinousBitSpec(19, 19, "p"); 847 private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond"); 848 private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond"); 849 private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc"); 850 private static final BitSpec d16hi = new ContinousBitSpec(21, 20, "d16hi"); 851 private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo"); 852 private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo); 853 // CBCond 854 private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo"); 855 private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi"); 856 private static final BitSpec c = new CompositeBitSpec(cHi, cLo); 857 private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond"); 858 private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2"); 859 private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo"); 860 private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, "d10Hi"); 861 private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo); 862 private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5"); 863 864 public abstract int setBits(int word, int value); 865 866 public abstract int getBits(int word); 867 868 public abstract int getWidth(); 869 870 public abstract boolean valueFits(int value); 871 } 872 873 public static class ContinousBitSpec extends BitSpec { 874 private final int hiBit; 875 private final int lowBit; 876 private final int width; 877 private final boolean signExt; 878 private final int mask; 879 private final String name; 880 881 public ContinousBitSpec(int hiBit, int lowBit, String name) { 882 this(hiBit, lowBit, false, name); 883 } 884 885 public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) { 886 super(); 887 this.hiBit = hiBit; 888 this.lowBit = lowBit; 889 this.signExt = signExt; 890 this.width = hiBit - lowBit + 1; 891 mask = ((1 << width) - 1) << lowBit; 892 this.name = name; 893 } 894 895 @Override 896 public int setBits(int word, int value) { 897 assert valueFits(value) : "Value: " + value + " does not fit in " + this; 898 return (word & ~mask) | ((value << lowBit) & mask); 899 } 900 901 @Override 902 public int getBits(int word) { 903 if (signExt) { 904 return ((word & mask) << (31 - hiBit)) >> (32 - width); 905 } else { 906 return (word & mask) >>> lowBit; 907 } 908 } 909 910 @Override 911 public int getWidth() { 912 return width; 913 } 914 915 @Override 916 public String toString() { 917 return String.format("%s [%d:%d]", name, hiBit, lowBit); 918 } 919 920 @Override 921 public boolean valueFits(int value) { 922 if (signExt) { 923 return isSimm(value, getWidth()); 924 } else { 925 return isImm(value, getWidth()); 926 } 927 } 928 } 929 930 public static class CompositeBitSpec extends BitSpec { 931 private final BitSpec left; 932 private final int leftWidth; 933 private final BitSpec right; 934 private final int rightWidth; 935 936 public CompositeBitSpec(BitSpec left, BitSpec right) { 937 super(); 938 this.left = left; 939 this.leftWidth = left.getWidth(); 940 this.right = right; 941 this.rightWidth = right.getWidth(); 942 } 943 944 @Override 945 public int getBits(int word) { 946 int l = left.getBits(word); 947 int r = right.getBits(word); 948 return l << rightWidth | r; 949 } 950 951 @Override 952 public int setBits(int word, int value) { 953 int l = leftBits(value); 954 int r = rightBits(value); 955 return left.setBits(right.setBits(word, r), l); 956 } 957 958 private int leftBits(int value) { 959 return SPARCAssembler.getBits(value, rightWidth + leftWidth, rightWidth); 960 } 961 962 private int rightBits(int value) { 963 return SPARCAssembler.getBits(value, rightWidth - 1, 0); 964 } 965 966 @Override 967 public int getWidth() { 968 return left.getWidth() + right.getWidth(); 969 } 970 971 @Override 972 public String toString() { 973 return String.format("CompositeBitSpec[%s, %s]", left, right); 974 } 975 976 @Override 977 public boolean valueFits(int value) { 978 return left.valueFits(leftBits(value)) && right.valueFits(rightBits(value)); 979 } 980 } 981 982 public static class BitKey { 983 private final BitSpec spec; 984 private final int value; 985 986 public BitKey(BitSpec spec, int value) { 987 super(); 988 this.spec = spec; 989 this.value = value; 990 } 991 992 @Override 993 public String toString() { 994 return String.format("BitKey %s=%s", spec, value); 995 } 996 } 997 998 /** 999 * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp. 1000 */ 1001 public static class BitKeyIndex { 1002 private final BitSpec spec; 1003 private final Map<Integer, BitKeyIndex> nodes; 1004 private SPARCOp op; 1005 1006 public BitKeyIndex(SPARCOp op) { 1007 assert op != null; 1008 this.op = op; 1009 this.nodes = null; 1010 this.spec = null; 1011 } 1012 1013 public BitKeyIndex(BitSpec spec) { 1014 assert spec != null; 1015 this.op = null; 1016 this.nodes = new HashMap<>(4); 1017 this.spec = spec; 1018 } 1019 1020 /** 1021 * Adds operation to the index. 1022 * 1023 * @param keys Ordered by the importance 1024 * @param operation Operation represented by this list of keys 1025 */ 1026 private void addOp(List<BitKey> keys, SPARCOp operation) { 1027 assert keys.size() > 0; 1028 BitKey first = keys.get(0); 1029 assert first.spec.equals(spec) : first.spec + " " + spec; 1030 BitKeyIndex node; 1031 if (keys.size() == 1) { 1032 if (nodes.containsKey(first.value)) { 1033 node = nodes.get(first.value); 1034 assert node.op == null : node + " " + keys; 1035 node.op = operation; 1036 } else { 1037 assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value); 1038 node = new BitKeyIndex(operation); 1039 } 1040 } else { 1041 node = nodes.get(first.value); 1042 if (node == null) { 1043 node = new BitKeyIndex(keys.get(1).spec); 1044 } 1045 node.addOp(keys.subList(1, keys.size()), operation); 1046 } 1047 nodes.put(first.value, node); 1048 } 1049 1050 /** 1051 * Finds the best matching {@link SPARCOp} for this instruction. 1052 */ 1053 public SPARCOp find(int inst) { 1054 if (nodes != null) { 1055 int key = spec.getBits(inst); 1056 BitKeyIndex sub = nodes.get(key); 1057 if (sub == null) { 1058 if (op != null) { 1059 return op; 1060 } else { 1061 throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes)); 1062 } 1063 } 1064 return sub.find(inst); 1065 } else { 1066 return this.op; 1067 } 1068 } 1069 1070 @Override 1071 public String toString() { 1072 return this.op == null ? this.spec + ": " + this.nodes : this.op.toString(); 1073 } 1074 } 1075 1076 public static final Bpcc BPCC = new Bpcc(Op2s.Bp); 1077 public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp); 1078 public static final CBCond CBCOND = new CBCond(); 1079 public static final Bpr BPR = new Bpr(); 1080 public static final Br BR = new Br(); 1081 public static final Sethi SETHI = new Sethi(); 1082 public static final Op3Op OP3 = new Op3Op(); 1083 public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp); 1084 public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp); 1085 public static final SPARCOp CALL = new SPARCOp(Ops.CallOp); 1086 private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op); 1087 1088 static { 1089 for (SPARCOp op : SPARCOp.OPS) { 1090 INDEX.addOp(op.getKeys(), op); 1091 } 1092 } 1093 1094 public static SPARCOp getSPARCOp(int inst) { 1095 return INDEX.find(inst); 1096 } 1097 1098 /** 1099 * Represents a class of SPARC instruction and gives methods to modify its fields. 1100 */ 1101 public static class SPARCOp { 1102 private final Ops op; 1103 private final BitKey opKey; 1104 private List<BitKey> keyFields; 1105 private static final List<SPARCOp> OPS = new ArrayList<>(); 1106 1107 public SPARCOp(Ops op) { 1108 super(); 1109 this.op = op; 1110 this.opKey = new BitKey(BitSpec.op, op.value); 1111 OPS.add(this); 1112 } 1113 1114 protected int setBits(int word) { 1115 return BitSpec.op.setBits(word, op.value); 1116 } 1117 1118 public boolean match(int inst) { 1119 for (BitKey k : keyFields) { 1120 if (k.spec.getBits(inst) != k.value) { 1121 return false; 1122 } 1123 } 1124 return true; 1125 } 1126 1127 protected List<BitKey> getKeys() { 1128 if (keyFields == null) { 1129 keyFields = new ArrayList<>(4); 1130 keyFields.add(opKey); 1131 } 1132 return keyFields; 1133 } 1134 1135 public Ops getOp(int inst) { 1136 return SPARCAssembler.OPS[BitSpec.op.getBits(inst)]; 1137 } 1138 1139 @Override 1140 public String toString() { 1141 String name = getClass().getName(); 1142 name = name.substring(name.lastIndexOf(".") + 1); 1143 return name + "[op: " + op + "]"; 1144 } 1145 } 1146 1147 /** 1148 * Base class for control transfer operations; provides access to the disp field. 1149 */ 1150 public abstract static class ControlTransferOp extends SPARCOp { 1151 private final Op2s op2; 1152 private final boolean delaySlot; 1153 private final BitSpec disp; 1154 private final BitKey op2Key; 1155 1156 private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) { 1157 super(op); 1158 this.op2 = op2; 1159 this.delaySlot = delaySlot; 1160 this.disp = disp; 1161 this.op2Key = new BitKey(BitSpec.op2, op2.value); 1162 } 1163 1164 public boolean hasDelaySlot() { 1165 return delaySlot; 1166 } 1167 1168 @Override 1169 protected int setBits(int word) { 1170 return BitSpec.op2.setBits(super.setBits(word), op2.value); 1171 } 1172 1173 protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) { 1174 if (lab.isBound()) { 1175 int d = (lab.position() - masm.position()) / 4; 1176 return setDisp(inst, d); 1177 } else { 1178 masm.patchUnbound(lab); 1179 return inst; 1180 } 1181 } 1182 1183 public int setDisp(int inst, int d) { 1184 assert this.match(inst); 1185 return this.disp.setBits(inst, d); 1186 } 1187 1188 public boolean isValidDisp(int d) { 1189 return this.disp.valueFits(d); 1190 } 1191 1192 public int setAnnul(int inst, boolean a) { 1193 return BitSpec.a.setBits(inst, a ? 1 : 0); 1194 } 1195 1196 @Override 1197 protected List<BitKey> getKeys() { 1198 List<BitKey> keys = super.getKeys(); 1199 keys.add(op2Key); 1200 return keys; 1201 } 1202 1203 public int getDisp(int inst) { 1204 return this.disp.getBits(inst); 1205 } 1206 1207 public abstract boolean isAnnulable(int inst); 1208 1209 public abstract boolean isConditional(int inst); 1210 } 1211 1212 public static class Bpcc extends ControlTransferOp { 1213 public Bpcc(Op2s op2) { 1214 super(Ops.BranchOp, op2, true, BitSpec.disp19); 1215 } 1216 1217 public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) { 1218 int inst = setBits(0); 1219 inst = BitSpec.a.setBits(inst, annul.flag); 1220 inst = BitSpec.cond.setBits(inst, cf.value); 1221 inst = BitSpec.cc.setBits(inst, cc.value); 1222 inst = BitSpec.p.setBits(inst, p.flag); 1223 masm.emitInt(setDisp(inst, masm, lab)); 1224 } 1225 1226 @Override 1227 public boolean isAnnulable(int inst) { 1228 return isConditional(inst); 1229 } 1230 1231 @Override 1232 public boolean isConditional(int inst) { 1233 int cond = BitSpec.cond.getBits(inst); 1234 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1235 } 1236 } 1237 1238 public static class Br extends ControlTransferOp { 1239 public Br() { 1240 super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22); 1241 } 1242 1243 @Override 1244 public boolean isAnnulable(int inst) { 1245 return isConditional(inst); 1246 } 1247 1248 @Override 1249 public boolean isConditional(int inst) { 1250 int cond = BitSpec.cond.getBits(inst); 1251 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1252 } 1253 } 1254 1255 public static class Bpr extends ControlTransferOp { 1256 private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0); 1257 1258 public Bpr() { 1259 super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16); 1260 } 1261 1262 public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) { 1263 int inst = setBits(0); 1264 inst = BitSpec.rcond.setBits(inst, rcond.value); 1265 inst = BitSpec.a.setBits(inst, a.flag); 1266 inst = BitSpec.p.setBits(inst, p.flag); 1267 inst = BitSpec.rs1.setBits(inst, rs1.encoding); 1268 masm.emitInt(setDisp(inst, masm, lab)); 1269 } 1270 1271 @Override 1272 protected List<BitKey> getKeys() { 1273 List<BitKey> keys = super.getKeys(); 1274 keys.add(CBCOND_KEY); 1275 return keys; 1276 } 1277 1278 @Override 1279 public boolean isAnnulable(int inst) { 1280 return isConditional(inst); 1281 } 1282 1283 @Override 1284 public boolean isConditional(int inst) { 1285 int cond = BitSpec.cond.getBits(inst); 1286 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1287 } 1288 } 1289 1290 public static final class CBCond extends ControlTransferOp { 1291 private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1); 1292 1293 private CBCond() { 1294 super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10); 1295 } 1296 1297 @Override 1298 protected List<BitKey> getKeys() { 1299 List<BitKey> keys = super.getKeys(); 1300 keys.add(CBCOND_KEY); 1301 return keys; 1302 } 1303 1304 public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) { 1305 int inst = setBits(0, cf, cc2, rs1); 1306 inst = BitSpec.rs2.setBits(inst, rs2.encoding); 1307 emit(masm, lab, inst); 1308 } 1309 1310 public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) { 1311 int inst = setBits(0, cf, cc2, rs1); 1312 inst = BitSpec.simm5.setBits(inst, simm5); 1313 emit(masm, lab, inst); 1314 } 1315 1316 private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) { 1317 int inst = baseInst; 1318 masm.insertNopAfterCBCond(); 1319 masm.emitInt(setDisp(inst, masm, lab)); 1320 } 1321 1322 private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) { 1323 int inst = super.setBits(base); 1324 inst = BitSpec.rs1.setBits(inst, rs1.encoding); 1325 inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0); 1326 inst = BitSpec.c.setBits(inst, cf.value); 1327 return BitSpec.cbcond.setBits(inst, 1); 1328 } 1329 1330 @Override 1331 public boolean isAnnulable(int inst) { 1332 return false; 1333 } 1334 1335 @Override 1336 public boolean isConditional(int inst) { 1337 return true; 1338 } 1339 } 1340 1341 public static class Op2Op extends SPARCOp { 1342 private final Op2s op2; 1343 private final BitKey op2Key; 1344 1345 public Op2Op(Ops op, Op2s op2) { 1346 super(op); 1347 this.op2 = op2; 1348 op2Key = new BitKey(BitSpec.op2, op2.value); 1349 } 1350 1351 @Override 1352 protected int setBits(int word) { 1353 int result = super.setBits(word); 1354 return BitSpec.op2.setBits(result, op2.value); 1355 } 1356 1357 @Override 1358 protected List<BitKey> getKeys() { 1359 List<BitKey> keys = super.getKeys(); 1360 keys.add(op2Key); 1361 return keys; 1362 } 1363 } 1364 1365 public static class Sethi extends Op2Op { 1366 public Sethi() { 1367 super(Ops.BranchOp, Op2s.Sethi); 1368 } 1369 1370 public Register getRS1(int word) { 1371 int regNum = BitSpec.rs1.getBits(word); 1372 return SPARC.cpuRegisters[regNum]; 1373 } 1374 1375 public int getImm22(int word) { 1376 return BitSpec.imm22.getBits(word); 1377 } 1378 1379 public boolean isNop(int inst) { 1380 return getRS1(inst).equals(g0) && getImm22(inst) == 0; 1381 } 1382 } 1383 1384 public static class Op3Op extends SPARCOp { 1385 public Op3Op() { 1386 super(ArithOp); 1387 } 1388 1389 public Op3s getOp3(int inst) { 1390 assert match(inst); 1391 return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)]; 1392 } 1393 } 1394 1395 public boolean hasFeature(CPUFeature feature) { 1396 return ((SPARC) this.target.arch).features.contains(feature); 1397 } 1398 1399 public static final int simm(int x, int nbits) { 1400 // assert_signed_range(x, nbits); 1401 return x & ((1 << nbits) - 1); 1402 } 1403 1404 public static final boolean isImm(int x, int nbits) { 1405 // assert_signed_range(x, nbits); 1406 return simm(x, nbits) == x; 1407 } 1408 1409 /** 1410 * Minimum value for signed immediate ranges. 1411 */ 1412 public static long minSimm(long nbits) { 1413 return -(1L << (nbits - 1)); 1414 } 1415 1416 /** 1417 * Maximum value for signed immediate ranges. 1418 */ 1419 public static long maxSimm(long nbits) { 1420 return (1L << (nbits - 1)) - 1; 1421 } 1422 1423 /** 1424 * Test if imm is within signed immediate range for nbits. 1425 */ 1426 public static boolean isSimm(long imm, int nbits) { 1427 return minSimm(nbits) <= imm && imm <= maxSimm(nbits); 1428 } 1429 1430 public static boolean isSimm10(long imm) { 1431 return isSimm(imm, 10); 1432 } 1433 1434 public static boolean isSimm11(long imm) { 1435 return isSimm(imm, 11); 1436 } 1437 1438 public static boolean isSimm11(JavaConstant constant) { 1439 return constant.isNull() || isSimm11(constant.asLong()); 1440 } 1441 1442 public static boolean isSimm5(JavaConstant constant) { 1443 return constant.isNull() || isSimm(constant.asLong(), 5); 1444 } 1445 1446 public static boolean isSimm13(int imm) { 1447 return isSimm(imm, 13); 1448 } 1449 1450 public static boolean isSimm13(JavaConstant constant) { 1451 long bits; 1452 switch (constant.getKind()) { 1453 case Double: 1454 bits = Double.doubleToRawLongBits(constant.asDouble()); 1455 break; 1456 case Float: 1457 bits = Float.floatToRawIntBits(constant.asFloat()); 1458 break; 1459 case Object: 1460 return JavaConstant.NULL_POINTER.equals(constant); 1461 default: 1462 bits = constant.asLong(); 1463 break; 1464 } 1465 return constant.isNull() || isSimm13(bits); 1466 } 1467 1468 public static boolean isSimm13(long imm) { 1469 return NumUtil.isInt(imm) && isSimm(imm, 13); 1470 } 1471 1472 public static boolean isWordDisp30(long imm) { 1473 return isSimm(imm, 30 + 2); 1474 } 1475 1476 public static final int hi22(int x) { 1477 return x >>> 10; 1478 } 1479 1480 public static final int lo10(int x) { 1481 return x & ((1 << 10) - 1); 1482 } 1483 1484 // @formatter:off 1485 /** 1486 * Instruction format for Fmt00 instructions. This abstraction is needed as it 1487 * makes the patching easier later on. 1488 * <pre> 1489 * | 00 | a | op2 | b | 1490 * |31 30|29 25|24 22|21 0| 1491 * </pre> 1492 */ 1493 // @formatter:on 1494 protected void fmt00(int a, int op2, int b) { 1495 assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b); 1496 int word = 0; 1497 BitSpec.op.setBits(word, 0); 1498 BitSpec.rd.setBits(word, a); 1499 BitSpec.op2.setBits(word, op2); 1500 BitSpec.imm22.setBits(word, b); 1501 emitInt(a << 25 | op2 << 22 | b); 1502 } 1503 1504 private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) { 1505 int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding); 1506 fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b); 1507 } 1508 1509 protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) { 1510 int b = rs2 == null ? 0 : rs2.encoding; 1511 int xBit = getXBit(op3); 1512 fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit); 1513 } 1514 1515 protected void op3(Op3s op3, Register rs1, int simm13, Register rd) { 1516 assert isSimm13(simm13); 1517 int i = 1 << 13; 1518 int simm13WithX = simm13 | getXBit(op3); 1519 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1)); 1520 } 1521 1522 // @formatter:off 1523 /** 1524 * Branch on Integer Condition Codes. 1525 * <pre> 1526 * | 00 |annul| cond| 010 | disp22 | 1527 * |31 30|29 |28 25|24 22|21 0| 1528 * </pre> 1529 */ 1530 // @formatter:on 1531 public void bicc(ConditionFlag cond, Annul annul, Label l) { 1532 bcc(Op2s.Br, cond, annul, l); 1533 } 1534 1535 // @formatter:off 1536 /** 1537 * Branch on Floating-Point Condition Codes. 1538 * <pre> 1539 * | 00 |annul| cond| 110 | disp22 | 1540 * |31 30|29 |28 25|24 22|21 0| 1541 * </pre> 1542 */ 1543 // @formatter:on 1544 public void fbcc(ConditionFlag cond, Annul annul, Label l) { 1545 bcc(Op2s.Fb, cond, annul, l); 1546 } 1547 1548 // @formatter:off 1549 /** 1550 * Branch on (Integer|Floatingpoint) Condition Codes. 1551 * <pre> 1552 * | 00 |annul| cond| op2 | disp22 | 1553 * |31 30|29 |28 25|24 22|21 0| 1554 * </pre> 1555 */ 1556 // @formatter:on 1557 private void bcc(Op2s op2, ConditionFlag cond, Annul annul, Label l) { 1558 insertNopAfterCBCond(); 1559 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; 1560 final int disp = 22; 1561 assert isSimm(pos, disp); 1562 pos &= (1 << disp) - 1; 1563 int a = (annul.flag << 4) | cond.getValue(); 1564 fmt00(a, op2.getValue(), pos); 1565 } 1566 1567 public void insertNopAfterCBCond() { 1568 int pos = position() - INSTRUCTION_SIZE; 1569 if (pos == 0) { 1570 return; 1571 } 1572 int inst = getInt(pos); 1573 if (isCBCond(inst)) { 1574 nop(); 1575 } 1576 } 1577 1578 protected static boolean isCBCond(int inst) { 1579 return isOp2(Ops.BranchOp, Op2s.Bpr, inst) && getBits(inst, 28, 28) == 1; 1580 } 1581 1582 private static boolean isOp2(Ops ops, Op2s op2s, int inst) { 1583 return getOp(inst).equals(ops) && getOp2(inst).equals(op2s); 1584 } 1585 1586 private static Ops getOp(int inst) { 1587 return OPS[getBits(inst, 31, 30)]; 1588 } 1589 1590 private static Op2s getOp2(int inst) { 1591 return OP2S[getBits(inst, 24, 22)]; 1592 } 1593 1594 public static int getBits(int inst, int hiBit, int lowBit) { 1595 return (inst >> lowBit) & ((1 << (hiBit - lowBit + 1)) - 1); 1596 } 1597 1598 // @formatter:off 1599 /** 1600 * Branch on Integer Condition Codes with Prediction. 1601 * <pre> 1602 * | 00 |an|cond | 001 |cc1 2|p | disp19 | 1603 * |31 30|29|28 25|24 22|21 20|19| 0| 1604 * </pre> 1605 */ 1606 // @formatter:on 1607 public void bpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { 1608 bpcc(Op2s.Bp, cond, annul, l, cc, predictTaken); 1609 } 1610 1611 // @formatter:off 1612 /** 1613 * Branch on Integer Condition Codes with Prediction. 1614 * <pre> 1615 * | 00 |an|cond | 101 |cc1 2|p | disp19 | 1616 * |31 30|29|28 25|24 22|21 20|19| 0| 1617 * </pre> 1618 */ 1619 // @formatter:on 1620 public void fbpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { 1621 bpcc(Op2s.Fbp, cond, annul, l, cc, predictTaken); 1622 } 1623 1624 // @formatter:off 1625 /** 1626 * Used for fbpcc (Float) and bpcc (Integer). 1627 * <pre> 1628 * | 00 |an|cond | op2 |cc1 2|p | disp19 | 1629 * |31 30|29|28 25|24 22|21 20|19| 0| 1630 * </pre> 1631 */ 1632 // @formatter:on 1633 private void bpcc(Op2s op2, ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { 1634 insertNopAfterCBCond(); 1635 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; 1636 final int disp = 19; 1637 assert isSimm(pos, disp); 1638 pos &= (1 << disp) - 1; 1639 int a = (annul.flag << 4) | cond.getValue(); 1640 int b = (cc.getValue() << 20) | ((predictTaken.flag) << 19) | pos; 1641 delaySlotOptimizationPoints.add(position()); 1642 fmt00(a, op2.getValue(), b); 1643 } 1644 1645 // @formatter:off 1646 /** 1647 * Branch on Integer Register with Prediction. 1648 * <pre> 1649 * | 00 |an| 0|rcond | 011 |d16hi|p | rs1 | d16lo | 1650 * |31 30|29|28|27 25 |24 22|21 20|19|18 14| 0| 1651 * </pre> 1652 */ 1653 // @formatter:on 1654 public void bpr(RCondition cond, Annul annul, Label l, BranchPredict predictTaken, Register rs1) { 1655 insertNopAfterCBCond(); 1656 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; 1657 final int disp = 16; 1658 assert isSimm(pos, disp); 1659 pos &= (1 << disp) - 1; 1660 int a = (annul.flag << 4) | cond.getValue(); 1661 int d16hi = (pos >> 13) << 13; 1662 int d16lo = d16hi ^ pos; 1663 int b = (d16hi << 20) | (predictTaken.flag << 19) | (rs1.encoding() << 14) | d16lo; 1664 delaySlotOptimizationPoints.add(position()); 1665 fmt00(a, Op2s.Bpr.getValue(), b); 1666 } 1667 1668 protected int patchUnbound(Label label) { 1669 label.addPatchAt(position()); 1670 return 0; 1671 } 1672 1673 public void cbcondw(ConditionFlag cf, Register rs1, Register rs2, Label lab) { 1674 cbcond(0, 0, cf, rs1, rs2.encoding, lab); 1675 } 1676 1677 public void cbcondw(ConditionFlag cf, Register rs1, int rs2, Label lab) { 1678 assert isSimm(rs2, 5); 1679 cbcond(0, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab); 1680 } 1681 1682 public void cbcondx(ConditionFlag cf, Register rs1, Register rs2, Label lab) { 1683 cbcond(1, 0, cf, rs1, rs2.encoding, lab); 1684 } 1685 1686 public void cbcondx(ConditionFlag cf, Register rs1, int rs2, Label lab) { 1687 assert isSimm(rs2, 5); 1688 cbcond(1, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab); 1689 } 1690 1691 private void cbcond(int cc2, int i, ConditionFlag cf, Register rs1, int rs2, Label l) { 1692 insertNopAfterCBCond(); 1693 int disp10 = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; 1694 assert isSimm(disp10, 10) && isImm(rs2, 5); 1695 disp10 &= (1 << 10) - 1; 1696 final int cLo = cf.value & 0b111; 1697 final int cHi = cf.value >> 3; 1698 final int d10Lo = disp10 & ((1 << 8) - 1); 1699 final int d10Hi = disp10 >> 8; 1700 int a = cHi << 4 | 0b1000 | cLo; 1701 int b = cc2 << 21 | d10Hi << D10HI_SHIFT | rs1.encoding << 14 | i << 13 | d10Lo << D10LO_SHIFT | rs2; 1702 fmt00(a, Op2s.Bpr.value, b); 1703 } 1704 1705 // @formatter:off 1706 /** 1707 * NOP. 1708 * <pre> 1709 * | 00 |00000| 100 | 0 | 1710 * |31 30|29 25|24 22|21 0| 1711 * </pre> 1712 */ 1713 // @formatter:on 1714 public void nop() { 1715 emitInt(1 << 24); 1716 } 1717 1718 public void sethi(int imm22, Register dst) { 1719 fmt00(dst.encoding, Op2s.Sethi.value, imm22); 1720 } 1721 1722 // @formatter:off 1723 /** 1724 * Instruction format for calls. 1725 * <pre> 1726 * | 01 | disp30 | 1727 * |31 30|29 0| 1728 * </pre> 1729 * 1730 * @return Position of the call instruction 1731 */ 1732 // @formatter:on 1733 public int call(int disp30) { 1734 assert isImm(disp30, 30); 1735 insertNopAfterCBCond(); 1736 int before = position(); 1737 int instr = 1 << 30; 1738 instr |= disp30; 1739 emitInt(instr); 1740 return before; 1741 } 1742 1743 public void add(Register rs1, Register rs2, Register rd) { 1744 op3(Add, rs1, rs2, rd); 1745 } 1746 1747 public void add(Register rs1, int simm13, Register rd) { 1748 op3(Add, rs1, simm13, rd); 1749 } 1750 1751 public void addc(Register rs1, Register rs2, Register rd) { 1752 op3(Addc, rs1, rs2, rd); 1753 } 1754 1755 public void addc(Register rs1, int simm13, Register rd) { 1756 op3(Addc, rs1, simm13, rd); 1757 } 1758 1759 public void addcc(Register rs1, Register rs2, Register rd) { 1760 op3(Addcc, rs1, rs2, rd); 1761 } 1762 1763 public void addcc(Register rs1, int simm13, Register rd) { 1764 op3(Addcc, rs1, simm13, rd); 1765 } 1766 1767 public void and(Register rs1, Register rs2, Register rd) { 1768 op3(And, rs1, rs2, rd); 1769 } 1770 1771 public void and(Register rs1, int simm13, Register rd) { 1772 op3(And, rs1, simm13, rd); 1773 } 1774 1775 public void andcc(Register rs1, Register rs2, Register rd) { 1776 op3(Andcc, rs1, rs2, rd); 1777 } 1778 1779 public void andcc(Register rs1, int simm13, Register rd) { 1780 op3(Andcc, rs1, simm13, rd); 1781 } 1782 1783 public void andn(Register rs1, Register rs2, Register rd) { 1784 op3(Andn, rs1, rs2, rd); 1785 } 1786 1787 public void andn(Register rs1, int simm13, Register rd) { 1788 op3(Andn, rs1, simm13, rd); 1789 } 1790 1791 public void andncc(Register rs1, Register rs2, Register rd) { 1792 op3(Andncc, rs1, rs2, rd); 1793 } 1794 1795 public void andncc(Register rs1, int simm13, Register rd) { 1796 op3(Andncc, rs1, simm13, rd); 1797 } 1798 1799 public void movwtos(Register rs2, Register rd) { 1800 assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd); 1801 op3(Impdep1, Movwtos, null, rs2, rd); 1802 } 1803 1804 public void umulxhi(Register rs1, Register rs2, Register rd) { 1805 op3(Impdep1, UMulxhi, rs1, rs2, rd); 1806 } 1807 1808 public void fdtos(Register rs2, Register rd) { 1809 assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd); 1810 op3(Fpop1, Fdtos, null, rs2, rd); 1811 } 1812 1813 public void movstouw(Register rs2, Register rd) { 1814 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1815 op3(Impdep1, Movstosw, null, rs2, rd); 1816 } 1817 1818 public void movstosw(Register rs2, Register rd) { 1819 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1820 op3(Impdep1, Movstosw, null, rs2, rd); 1821 } 1822 1823 public void movdtox(Register rs2, Register rd) { 1824 assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1825 op3(Impdep1, Movdtox, null, rs2, rd); 1826 } 1827 1828 public void movxtod(Register rs2, Register rd) { 1829 assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd); 1830 op3(Impdep1, Movxtod, null, rs2, rd); 1831 } 1832 1833 public void fadds(Register rs1, Register rs2, Register rd) { 1834 op3(Fpop1, Fadds, rs1, rs2, rd); 1835 } 1836 1837 public void faddd(Register rs1, Register rs2, Register rd) { 1838 op3(Fpop1, Faddd, rs1, rs2, rd); 1839 } 1840 1841 public void faddq(Register rs1, Register rs2, Register rd) { 1842 op3(Fpop1, Faddq, rs1, rs2, rd); 1843 } 1844 1845 public void fdivs(Register rs1, Register rs2, Register rd) { 1846 op3(Fpop1, Fdivs, rs1, rs2, rd); 1847 } 1848 1849 public void fdivd(Register rs1, Register rs2, Register rd) { 1850 op3(Fpop1, Fdivd, rs1, rs2, rd); 1851 } 1852 1853 public void fmovs(Register rs2, Register rd) { 1854 op3(Fpop1, Fmovs, null, rs2, rd); 1855 } 1856 1857 public void fmovd(Register rs2, Register rd) { 1858 op3(Fpop1, Fmovd, null, rs2, rd); 1859 } 1860 1861 public void fsrc2s(Register rs2, Register rd) { 1862 op3(Impdep1, Fsrc2s, null, rs2, rd); 1863 } 1864 1865 public void fsrc2d(Register rs2, Register rd) { 1866 op3(Impdep1, Fsrc2d, null, rs2, rd); 1867 } 1868 1869 public void fmuls(Register rs1, Register rs2, Register rd) { 1870 op3(Fpop1, Fmuls, rs1, rs2, rd); 1871 } 1872 1873 public void fsmuld(Register rs1, Register rs2, Register rd) { 1874 op3(Fpop1, Fsmuld, rs1, rs2, rd); 1875 } 1876 1877 public void fmuld(Register rs1, Register rs2, Register rd) { 1878 op3(Fpop1, Fmuld, rs1, rs2, rd); 1879 } 1880 1881 public void fnegs(Register rs2, Register rd) { 1882 op3(Fpop1, Fnegs, null, rs2, rd); 1883 } 1884 1885 public void fnegd(Register rs2, Register rd) { 1886 op3(Fpop1, Fnegd, null, rs2, rd); 1887 } 1888 1889 /** 1890 * Helper method to determine if the instruction needs the X bit set. 1891 */ 1892 private static int getXBit(Op3s op3) { 1893 switch (op3) { 1894 case Sllx: 1895 case Srax: 1896 case Srlx: 1897 return 1 << 12; 1898 default: 1899 return 0; 1900 } 1901 } 1902 1903 public void fstoi(Register rs2, Register rd) { 1904 op3(Fpop1, Fstoi, null, rs2, rd); 1905 } 1906 1907 public void fstox(Register rs2, Register rd) { 1908 op3(Fpop1, Fstox, null, rs2, rd); 1909 } 1910 1911 public void fdtox(Register rs2, Register rd) { 1912 op3(Fpop1, Fdtox, null, rs2, rd); 1913 } 1914 1915 public void fstod(Register rs2, Register rd) { 1916 op3(Fpop1, Fstod, null, rs2, rd); 1917 } 1918 1919 public void fdtoi(Register rs2, Register rd) { 1920 op3(Fpop1, Fdtoi, null, rs2, rd); 1921 } 1922 1923 public void fitos(Register rs2, Register rd) { 1924 op3(Fpop1, Fitos, null, rs2, rd); 1925 } 1926 1927 public void fitod(Register rs2, Register rd) { 1928 op3(Fpop1, Fitod, null, rs2, rd); 1929 } 1930 1931 public void fxtos(Register rs2, Register rd) { 1932 op3(Fpop1, Fxtos, null, rs2, rd); 1933 } 1934 1935 public void fxtod(Register rs2, Register rd) { 1936 op3(Fpop1, Fxtod, null, rs2, rd); 1937 } 1938 1939 public void fzeros(Register rd) { 1940 op3(Impdep1, Fzeros, null, null, rd); 1941 } 1942 1943 public void fzerod(Register rd) { 1944 op3(Impdep1, Fzerod, null, null, rd); 1945 } 1946 1947 public void flushw() { 1948 op3(Flushw, g0, g0, g0); 1949 } 1950 1951 public void fsqrtd(Register rs2, Register rd) { 1952 op3(Fpop1, Fsqrtd, null, rs2, rd); 1953 } 1954 1955 public void fsqrts(Register rs2, Register rd) { 1956 op3(Fpop1, Fsqrts, null, rs2, rd); 1957 } 1958 1959 public void fabss(Register rs2, Register rd) { 1960 op3(Fpop1, Fabss, null, rs2, rd); 1961 } 1962 1963 public void fabsd(Register rs2, Register rd) { 1964 op3(Fpop1, Fabsd, null, rs2, rd); 1965 } 1966 1967 public void fsubs(Register rs1, Register rs2, Register rd) { 1968 op3(Fpop1, Fsubs, rs1, rs2, rd); 1969 } 1970 1971 public void fsubd(Register rs1, Register rs2, Register rd) { 1972 op3(Fpop1, Fsubd, rs1, rs2, rd); 1973 } 1974 1975 // @formatter:off 1976 /** 1977 * Instruction format for fcmp. 1978 * <pre> 1979 * | 10 | --- |cc1|cc0|desc | rs1 | opf | rs2 | 1980 * |31 30|29 27|26 |25 |24 19|18 14|13 5|4 0| 1981 * </pre> 1982 */ 1983 // @formatter:on 1984 public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) { 1985 int a = cc.value; 1986 int b = opf.value << 5 | rs2.encoding; 1987 delaySlotOptimizationPoints.add(position()); 1988 fmt10(a, Fcmp.value, rs1.encoding, b); 1989 } 1990 1991 // @formatter:off 1992 /** 1993 * Instruction format for most arithmetic stuff. 1994 * <pre> 1995 * | 10 | rd | op3 | rs1 | b | 1996 * |31 30|29 25|24 19|18 14|13 0| 1997 * </pre> 1998 */ 1999 // @formatter:on 2000 protected void fmt10(int rd, int op3, int rs1, int b) { 2001 fmt(0b10, rd, op3, rs1, b); 2002 } 2003 2004 // @formatter:off 2005 /** 2006 * Instruction format for most arithmetic stuff. 2007 * <pre> 2008 * | op | rd | op3 | rs1 | b | 2009 * |31 30|29 25|24 19|18 14|13 0| 2010 * </pre> 2011 */ 2012 // @formatter:on 2013 protected void fmt(int op, int rd, int op3, int rs1, int b) { 2014 assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b); 2015 int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b; 2016 emitInt(instr); 2017 } 2018 2019 public void illtrap(int const22) { 2020 fmt00(0, Op2s.Illtrap.value, const22); 2021 } 2022 2023 public void jmpl(Register rs1, Register rs2, Register rd) { 2024 insertNopAfterCBCond(); 2025 op3(Jmpl, rs1, rs2, rd); 2026 } 2027 2028 /** 2029 * @return Position of the jmpl instruction 2030 */ 2031 public int jmpl(Register rs1, int simm13, Register rd) { 2032 insertNopAfterCBCond(); 2033 int before = position(); 2034 op3(Jmpl, rs1, simm13, rd); 2035 return before; 2036 } 2037 2038 public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) { 2039 fmovcc(cond, cc, rs2, rd, Fmovdcc.value); 2040 } 2041 2042 public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) { 2043 fmovcc(cond, cc, rs2, rd, Fmovscc.value); 2044 } 2045 2046 private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) { 2047 int opfCC = cc.value; 2048 int a = opfCC << 11 | opfLow << 5 | rs2.encoding; 2049 fmt10(rd.encoding, Fpop2.value, cond.value, a); 2050 } 2051 2052 public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) { 2053 movcc(conditionFlag, cc, 0, rs2.encoding, rd); 2054 } 2055 2056 public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) { 2057 assert isSimm11(simm11); 2058 movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd); 2059 } 2060 2061 private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) { 2062 int cc01 = 0b11 & cc.value; 2063 int cc2 = cc.isFloat ? 0 : 1; 2064 int a = cc2 << 4 | conditionFlag.value; 2065 int b = cc01 << 11 | i << 13 | imm; 2066 fmt10(rd.encoding, Movcc.value, a, b); 2067 } 2068 2069 public void mulx(Register rs1, Register rs2, Register rd) { 2070 op3(Mulx, rs1, rs2, rd); 2071 } 2072 2073 public void mulx(Register rs1, int simm13, Register rd) { 2074 op3(Mulx, rs1, simm13, rd); 2075 } 2076 2077 public void or(Register rs1, Register rs2, Register rd) { 2078 assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd); 2079 op3(Or, rs1, rs2, rd); 2080 } 2081 2082 public void or(Register rs1, int simm13, Register rd) { 2083 assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd); 2084 op3(Or, rs1, simm13, rd); 2085 } 2086 2087 public void popc(Register rs2, Register rd) { 2088 op3(Popc, g0, rs2, rd); 2089 } 2090 2091 public void popc(int simm13, Register rd) { 2092 op3(Popc, g0, simm13, rd); 2093 } 2094 2095 public void prefetch(SPARCAddress addr, Fcn fcn) { 2096 Register rs1 = addr.getBase(); 2097 if (addr.getIndex().equals(Register.None)) { 2098 int dis = addr.getDisplacement(); 2099 assert isSimm13(dis); 2100 fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1)); 2101 } else { 2102 Register rs2 = addr.getIndex(); 2103 fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding); 2104 } 2105 } 2106 2107 // A.44 Read State Register 2108 2109 public void rdpc(Register rd) { 2110 op3(Rd, r5, g0, rd); 2111 } 2112 2113 public void restore(Register rs1, Register rs2, Register rd) { 2114 op3(Restore, rs1, rs2, rd); 2115 } 2116 2117 public static final int PC_RETURN_OFFSET = 8; 2118 2119 public void save(Register rs1, Register rs2, Register rd) { 2120 op3(Save, rs1, rs2, rd); 2121 } 2122 2123 public void save(Register rs1, int simm13, Register rd) { 2124 op3(Save, rs1, simm13, rd); 2125 } 2126 2127 public void sdivx(Register rs1, Register rs2, Register rd) { 2128 op3(Sdivx, rs1, rs2, rd); 2129 } 2130 2131 public void sdivx(Register rs1, int simm13, Register rd) { 2132 op3(Sdivx, rs1, simm13, rd); 2133 } 2134 2135 public void udivx(Register rs1, Register rs2, Register rd) { 2136 op3(Udivx, rs1, rs2, rd); 2137 } 2138 2139 public void udivx(Register rs1, int simm13, Register rd) { 2140 op3(Udivx, rs1, simm13, rd); 2141 } 2142 2143 public void sll(Register rs1, Register rs2, Register rd) { 2144 op3(Sll, rs1, rs2, rd); 2145 } 2146 2147 public void sll(Register rs1, int shcnt32, Register rd) { 2148 assert isImm(shcnt32, 5); 2149 op3(Sll, rs1, shcnt32, rd); 2150 } 2151 2152 public void sllx(Register rs1, Register rs2, Register rd) { 2153 op3(Sllx, rs1, rs2, rd); 2154 } 2155 2156 public void sllx(Register rs1, int shcnt64, Register rd) { 2157 assert isImm(shcnt64, 6); 2158 op3(Sllx, rs1, shcnt64, rd); 2159 } 2160 2161 public void sra(Register rs1, Register rs2, Register rd) { 2162 op3(Sra, rs1, rs2, rd); 2163 } 2164 2165 public void sra(Register rs1, int simm13, Register rd) { 2166 op3(Sra, rs1, simm13, rd); 2167 } 2168 2169 public void srax(Register rs1, Register rs2, Register rd) { 2170 op3(Srax, rs1, rs2, rd); 2171 } 2172 2173 public void srax(Register rs1, int shcnt64, Register rd) { 2174 assert isImm(shcnt64, 6); 2175 op3(Srax, rs1, shcnt64, rd); 2176 } 2177 2178 public void srl(Register rs1, Register rs2, Register rd) { 2179 op3(Srl, rs1, rs2, rd); 2180 } 2181 2182 public void srl(Register rs1, int simm13, Register rd) { 2183 op3(Srl, rs1, simm13, rd); 2184 } 2185 2186 public void srlx(Register rs1, Register rs2, Register rd) { 2187 op3(Srlx, rs1, rs2, rd); 2188 } 2189 2190 public void srlx(Register rs1, int shcnt64, Register rd) { 2191 assert isImm(shcnt64, 6); 2192 op3(Srlx, rs1, shcnt64, rd); 2193 } 2194 2195 public void fandd(Register rs1, Register rs2, Register rd) { 2196 op3(Impdep1, Fandd, rs1, rs2, rd); 2197 } 2198 2199 public void sub(Register rs1, Register rs2, Register rd) { 2200 op3(Sub, rs1, rs2, rd); 2201 } 2202 2203 public void sub(Register rs1, int simm13, Register rd) { 2204 op3(Sub, rs1, simm13, rd); 2205 } 2206 2207 public void subcc(Register rs1, Register rs2, Register rd) { 2208 op3(Subcc, rs1, rs2, rd); 2209 } 2210 2211 public void subcc(Register rs1, int simm13, Register rd) { 2212 op3(Subcc, rs1, simm13, rd); 2213 } 2214 2215 public void ta(int trap) { 2216 tcc(Icc, Always, trap); 2217 } 2218 2219 public void tcc(CC cc, ConditionFlag flag, int trap) { 2220 assert isImm(trap, 8); 2221 int b = cc.value << 11; 2222 b |= 1 << 13; 2223 b |= trap; 2224 fmt10(flag.value, Op3s.Tcc.getValue(), 0, b); 2225 } 2226 2227 public void wrccr(Register rs1, Register rs2) { 2228 op3(Wr, rs1, rs2, r2); 2229 } 2230 2231 public void wrccr(Register rs1, int simm13) { 2232 op3(Wr, rs1, simm13, r2); 2233 } 2234 2235 public void xor(Register rs1, Register rs2, Register rd) { 2236 op3(Xor, rs1, rs2, rd); 2237 } 2238 2239 public void xor(Register rs1, int simm13, Register rd) { 2240 op3(Xor, rs1, simm13, rd); 2241 } 2242 2243 public void xorcc(Register rs1, Register rs2, Register rd) { 2244 op3(Xorcc, rs1, rs2, rd); 2245 } 2246 2247 public void xorcc(Register rs1, int simm13, Register rd) { 2248 op3(Xorcc, rs1, simm13, rd); 2249 } 2250 2251 public void xnor(Register rs1, Register rs2, Register rd) { 2252 op3(Xnor, rs1, rs2, rd); 2253 } 2254 2255 public void xnor(Register rs1, int simm13, Register rd) { 2256 op3(Xnor, rs1, simm13, rd); 2257 } 2258 2259 /* 2260 * Load/Store 2261 */ 2262 protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) { 2263 Register rs1 = addr.getBase(); 2264 if (!addr.getIndex().equals(Register.None)) { 2265 Register rs2 = addr.getIndex(); 2266 if (asi != null) { 2267 int b = rs2.encoding; 2268 b |= asi.value << 5; 2269 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b); 2270 } else { 2271 op3(op3, rs1, rs2, rd); 2272 } 2273 } else { 2274 int imm = addr.getDisplacement(); 2275 op3(op3, rs1, imm, rd); 2276 } 2277 } 2278 2279 protected void ld(Op3s op3, SPARCAddress addr, Register rd) { 2280 ld(op3, addr, rd, null); 2281 } 2282 2283 public void lddf(SPARCAddress src, Register dst) { 2284 assert isDoubleFloatRegister(dst) : dst; 2285 ld(Lddf, src, dst); 2286 } 2287 2288 public void ldf(SPARCAddress src, Register dst) { 2289 assert isSingleFloatRegister(dst) : dst; 2290 ld(Ldf, src, dst); 2291 } 2292 2293 public void lduh(SPARCAddress src, Register dst) { 2294 assert isCPURegister(dst) : dst; 2295 ld(Lduh, src, dst); 2296 } 2297 2298 public void ldsh(SPARCAddress src, Register dst) { 2299 assert isCPURegister(dst) : dst; 2300 ld(Ldsh, src, dst); 2301 } 2302 2303 public void ld(SPARCAddress src, Register dst, int bytes, boolean signed) { 2304 if (signed) { 2305 switch (bytes) { 2306 case 1: 2307 ldub(src, dst); 2308 break; 2309 case 2: 2310 lduh(src, dst); 2311 break; 2312 case 4: 2313 lduw(src, dst); 2314 break; 2315 case 8: 2316 ldx(src, dst); 2317 break; 2318 default: 2319 throw new InternalError(); 2320 } 2321 } else { 2322 switch (bytes) { 2323 case 1: 2324 ldsb(src, dst); 2325 break; 2326 case 2: 2327 ldsh(src, dst); 2328 break; 2329 case 4: 2330 ldsw(src, dst); 2331 break; 2332 case 8: 2333 ldx(src, dst); 2334 break; 2335 default: 2336 throw new InternalError(); 2337 } 2338 } 2339 } 2340 2341 public void ldub(SPARCAddress src, Register dst) { 2342 assert isCPURegister(dst) : dst; 2343 ld(Ldub, src, dst); 2344 } 2345 2346 public void ldsb(SPARCAddress src, Register dst) { 2347 assert isCPURegister(dst) : dst; 2348 ld(Ldsb, src, dst); 2349 } 2350 2351 public void lduw(SPARCAddress src, Register dst) { 2352 assert isCPURegister(dst) : dst; 2353 ld(Lduw, src, dst); 2354 } 2355 2356 public void ldsw(SPARCAddress src, Register dst) { 2357 assert isCPURegister(dst) : dst; 2358 ld(Ldsw, src, dst); 2359 } 2360 2361 public void ldx(SPARCAddress src, Register dst) { 2362 assert isCPURegister(dst) : dst; 2363 ld(Ldx, src, dst); 2364 } 2365 2366 public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) { 2367 assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); 2368 ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi); 2369 } 2370 2371 public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) { 2372 assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); 2373 ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi); 2374 } 2375 2376 protected void st(Op3s op3, Register rs1, SPARCAddress dest) { 2377 ld(op3, dest, rs1); 2378 } 2379 2380 public void stdf(Register rd, SPARCAddress addr) { 2381 assert isDoubleFloatRegister(rd) : rd; 2382 st(Stdf, rd, addr); 2383 } 2384 2385 public void stf(Register rd, SPARCAddress addr) { 2386 assert isSingleFloatRegister(rd) : rd; 2387 st(Stf, rd, addr); 2388 } 2389 2390 public void stb(Register rd, SPARCAddress addr) { 2391 assert isCPURegister(rd) : rd; 2392 st(Stb, rd, addr); 2393 } 2394 2395 public void sth(Register rd, SPARCAddress addr) { 2396 assert isCPURegister(rd) : rd; 2397 st(Sth, rd, addr); 2398 } 2399 2400 public void stw(Register rd, SPARCAddress addr) { 2401 assert isCPURegister(rd) : rd; 2402 st(Stw, rd, addr); 2403 } 2404 2405 public void stx(Register rd, SPARCAddress addr) { 2406 assert isCPURegister(rd) : rd; 2407 st(Stx, rd, addr); 2408 } 2409 2410 public void membar(int barriers) { 2411 op3(Membar, r15, barriers, g0); 2412 } 2413 2414 public void casa(Register rs1, Register rs2, Register rd, Asi asi) { 2415 ld(Casa, new SPARCAddress(rs1, rs2), rd, asi); 2416 } 2417 2418 public void casxa(Register rs1, Register rs2, Register rd, Asi asi) { 2419 ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi); 2420 } 2421 2422 @Override 2423 public InstructionCounter getInstructionCounter() { 2424 return new SPARCInstructionCounter(this); 2425 } 2426 2427 public void patchAddImmediate(int position, int simm13) { 2428 int inst = getInt(position); 2429 assert SPARCAssembler.isSimm13(simm13) : simm13; 2430 assert (inst >>> 30) == 0b10 : String.format("0x%x", inst); 2431 assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst); 2432 assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst); 2433 inst = inst & (~((1 << 13) - 1)); 2434 inst |= simm13 & ((1 << 12) - 1); 2435 emitInt(inst, position); 2436 } 2437 2438 public void fpadd32(Register rs1, Register rs2, Register rd) { 2439 op3(Impdep1, Fpadd32, rs1, rs2, rd); 2440 } 2441 2442 /** 2443 * Does peephole optimization on code generated by this assembler. This method should be called 2444 * at the end of code generation. 2445 * <p> 2446 * It searches for conditional branch instructions which has nop in the delay slot then looks at 2447 * the instruction at branch target; if it is an arithmetic instruction, which does not throw an 2448 * exception (e.g. division), it pulls this instruction into the delay slot and increments the 2449 * displacement by 1. 2450 */ 2451 public void peephole() { 2452 for (int i : delaySlotOptimizationPoints) { 2453 optimizeDelaySlot(i); 2454 } 2455 } 2456 2457 /** 2458 * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff 2459 * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul 2460 * flag and increments <i>b</i>s disp field by 1; 2461 * <p> 2462 * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to 2463 * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp 2464 * field to <i>b</i>s disp field. 2465 */ 2466 private void optimizeDelaySlot(int i) { 2467 int delaySlotAbsolute = i + INSTRUCTION_SIZE; 2468 int nextInst = getInt(delaySlotAbsolute); 2469 SPARCOp nextOp = getSPARCOp(nextInst); 2470 if (nextOp instanceof Sethi && ((Sethi) nextOp).isNop(nextInst)) { 2471 int inst = getInt(i); 2472 SPARCOp op = getSPARCOp(inst); 2473 if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) { 2474 ControlTransferOp ctOp = (ControlTransferOp) op; 2475 int disp = ctOp.getDisp(inst); 2476 int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE; 2477 int branchTargetInst = getInt(branchTargetAbsolute); 2478 SPARCOp branchTargetOp = getSPARCOp(branchTargetInst); 2479 if (branchTargetOp instanceof Op3Op) { 2480 Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst); 2481 if (!op3.throwsException()) { 2482 inst = ctOp.setDisp(inst, disp + 1); // Increment the offset 2483 inst = ctOp.setAnnul(inst, true); 2484 emitInt(inst, i); 2485 emitInt(branchTargetInst, delaySlotAbsolute); 2486 } 2487 } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) { 2488 // If branchtarget is a unconditional branch 2489 ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp; 2490 int btDisp = branchTargetOpBranch.getDisp(branchTargetInst); 2491 int newDisp = disp + btDisp; 2492 if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size 2493 int instAfter = ctOp.setDisp(inst, newDisp); 2494 instAfter = ctOp.setAnnul(instAfter, true); 2495 branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE); 2496 branchTargetOp = getSPARCOp(branchTargetInst); 2497 if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) { 2498 emitInt(instAfter, i); 2499 emitInt(branchTargetInst, delaySlotAbsolute); 2500 } 2501 } 2502 } 2503 } 2504 } 2505 } 2506}