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