1 /* 2 * Copyright (c) 2009, 2019, 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.BranchTargetOutOfBoundsException; 140 import org.graalvm.compiler.asm.Label; 141 import org.graalvm.compiler.core.common.NumUtil; 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 getOpfCCValue()631 public int getOpfCCValue() { 632 /* 633 * In the opf_cc encoding for FMOVcc, the third bit is set to indicate icc/xcc. 634 */ 635 return (isFloat ? value : (value | 0x4)); 636 } 637 getOperator()638 public String getOperator() { 639 return operator; 640 } 641 forKind(PlatformKind kind)642 public static CC forKind(PlatformKind kind) { 643 if (kind.equals(SPARCKind.XWORD)) { 644 return Xcc; 645 } else if (kind.equals(SPARCKind.WORD)) { 646 return Icc; 647 } else if (kind.equals(SPARCKind.SINGLE) || kind.equals(SPARCKind.DOUBLE)) { 648 return Fcc0; 649 } else { 650 throw new IllegalArgumentException("Unknown kind: " + kind); 651 } 652 } 653 } 654 655 public enum ConditionFlag { 656 // @formatter:off 657 658 // for FBfcc & FBPfcc instruction 659 F_Never(0, "f_never"), 660 F_NotEqual(1, "f_notEqual"), 661 F_LessOrGreater(2, "f_lessOrGreater"), 662 F_UnorderedOrLess(3, "f_unorderedOrLess"), 663 F_Less(4, "f_less"), 664 F_UnorderedOrGreater(5, "f_unorderedOrGreater"), 665 F_Greater(6, "f_greater"), 666 F_Unordered(7, "f_unordered"), 667 F_Always(8, "f_always"), 668 F_Equal(9, "f_equal"), 669 F_UnorderedOrEqual(10, "f_unorderedOrEqual"), 670 F_GreaterOrEqual(11, "f_greaterOrEqual"), 671 F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"), 672 F_LessOrEqual(13, "f_lessOrEqual"), 673 F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"), 674 F_Ordered(15, "f_ordered"), 675 676 // for integers 677 Never(0, "never"), 678 Equal(1, "equal", true), 679 Zero(1, "zero"), 680 LessEqual(2, "lessEqual", true), 681 Less(3, "less", true), 682 LessEqualUnsigned(4, "lessEqualUnsigned", true), 683 LessUnsigned(5, "lessUnsigned", true), 684 CarrySet(5, "carrySet"), 685 Negative(6, "negative", true), 686 OverflowSet(7, "overflowSet", true), 687 Always(8, "always"), 688 NotEqual(9, "notEqual", true), 689 NotZero(9, "notZero"), 690 Greater(10, "greater", true), 691 GreaterEqual(11, "greaterEqual", true), 692 GreaterUnsigned(12, "greaterUnsigned", true), 693 GreaterEqualUnsigned(13, "greaterEqualUnsigned", true), 694 CarryClear(13, "carryClear"), 695 Positive(14, "positive", true), 696 OverflowClear(15, "overflowClear", true); 697 698 // @formatter:on 699 700 private final int value; 701 private final String operator; 702 private boolean forCBcond = false; 703 ConditionFlag(int value, String op)704 ConditionFlag(int value, String op) { 705 this(value, op, false); 706 } 707 ConditionFlag(int value, String op, boolean cbcond)708 ConditionFlag(int value, String op, boolean cbcond) { 709 this.value = value; 710 this.operator = op; 711 this.forCBcond = cbcond; 712 } 713 isCBCond()714 public boolean isCBCond() { 715 return forCBcond; 716 } 717 getValue()718 public int getValue() { 719 return value; 720 } 721 getOperator()722 public String getOperator() { 723 return operator; 724 } 725 negate()726 public ConditionFlag negate() { 727 //@formatter:off 728 switch (this) { 729 case F_Never : return F_Always; 730 case F_Always : return F_Never; 731 case F_NotEqual : return F_Equal; 732 case F_Equal : return F_NotEqual; 733 case F_LessOrGreater : return F_UnorderedOrEqual; 734 case F_UnorderedOrEqual : return F_LessOrGreater; 735 case F_Less : return F_UnorderedGreaterOrEqual; 736 case F_UnorderedGreaterOrEqual: return F_Less; 737 case F_LessOrEqual : return F_UnorderedOrGreater; 738 case F_UnorderedOrGreater : return F_LessOrEqual; 739 case F_Greater : return F_UnorderedOrLessOrEqual; 740 case F_UnorderedOrLessOrEqual : return F_Greater; 741 case F_GreaterOrEqual : return F_UnorderedOrLess; 742 case F_UnorderedOrLess : return F_GreaterOrEqual; 743 case F_Unordered : return F_Ordered; 744 case F_Ordered : return F_Unordered; 745 case Never : return Always; 746 case Always : return Never; 747 case Equal : return NotEqual; 748 case NotEqual : return Equal; 749 case Zero : return NotZero; 750 case NotZero : return Zero; 751 case LessEqual : return Greater; 752 case Greater : return LessEqual; 753 case Less : return GreaterEqual; 754 case GreaterEqual : return Less; 755 case LessEqualUnsigned : return GreaterUnsigned; 756 case GreaterUnsigned : return LessEqualUnsigned; 757 case LessUnsigned : return GreaterEqualUnsigned; 758 case GreaterEqualUnsigned : return LessUnsigned; 759 case CarrySet : return CarryClear; 760 case CarryClear : return CarrySet; 761 case Negative : return Positive; 762 case Positive : return Negative; 763 case OverflowSet : return OverflowClear; 764 case OverflowClear : return OverflowSet; 765 default: 766 throw new InternalError(); 767 } 768 //@formatter:on 769 } 770 mirror()771 public ConditionFlag mirror() { 772 switch (this) { 773 //@formatter:off 774 case F_Less : return F_Greater; 775 case F_Greater : return F_Less; 776 case F_LessOrEqual : return F_GreaterOrEqual; 777 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual; 778 case F_UnorderedOrGreater : return F_UnorderedOrLess; 779 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual; 780 case F_GreaterOrEqual : return F_LessOrEqual; 781 case F_UnorderedOrLess : return F_UnorderedOrGreater; 782 case LessEqual : return GreaterEqual; 783 case Greater : return Less; 784 case Less : return Greater; 785 case GreaterEqual : return LessEqual; 786 case LessEqualUnsigned : return GreaterEqualUnsigned; 787 case GreaterUnsigned : return LessUnsigned; 788 case LessUnsigned : return GreaterUnsigned; 789 case GreaterEqualUnsigned : return LessEqualUnsigned; 790 default: 791 return this; 792 //@formatter:on 793 } 794 } 795 796 } 797 798 public enum RCondition { 799 // @formatter:off 800 801 Rc_z(0b001, "rc_z"), 802 Rc_lez(0b010, "rc_lez"), 803 Rc_lz(0b011, "rc_lz"), 804 Rc_nz(0b101, "rc_nz"), 805 Rc_gz(0b110, "rc_gz"), 806 Rc_gez(0b111, "rc_gez"), 807 Rc_last(Rc_gez.getValue(), "rc_last"); 808 809 // @formatter:on 810 811 private final int value; 812 private final String operator; 813 RCondition(int value, String op)814 RCondition(int value, String op) { 815 this.value = value; 816 this.operator = op; 817 } 818 getValue()819 public int getValue() { 820 return value; 821 } 822 getOperator()823 public String getOperator() { 824 return operator; 825 } 826 } 827 828 /** 829 * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture. 830 */ 831 public enum Asi { 832 // @formatter:off 833 834 INVALID(-1), 835 ASI_PRIMARY(0x80), 836 ASI_PRIMARY_NOFAULT(0x82), 837 ASI_PRIMARY_LITTLE(0x88), 838 // Block initializing store 839 ASI_ST_BLKINIT_PRIMARY(0xE2), 840 // Most-Recently-Used (MRU) BIS variant 841 ASI_ST_BLKINIT_MRU_PRIMARY(0xF2); 842 843 // @formatter:on 844 845 private final int value; 846 Asi(int value)847 Asi(int value) { 848 this.value = value; 849 } 850 getValue()851 public int getValue() { 852 return value; 853 } 854 isValid()855 public boolean isValid() { 856 return value != INVALID.getValue(); 857 } 858 } 859 860 public enum Fcn { 861 SeveralWritesAndPossiblyReads(2), 862 SeveralReadsWeak(0), 863 OneRead(1), 864 OneWrite(3), 865 Page(4), 866 NearestUnifiedCache(17), 867 SeveralReadsStrong(20), 868 OneReadStrong(21), 869 SeveralWritesAndPossiblyReadsStrong(22), 870 OneWriteStrong(23); 871 872 private final int value; 873 Fcn(int value)874 Fcn(int value) { 875 this.value = value; 876 } 877 getValue()878 public int getValue() { 879 return value; 880 } 881 } 882 883 /** 884 * Specifies various bit fields used in SPARC instructions. 885 */ 886 @SuppressWarnings("unused") 887 public abstract static class BitSpec { 888 private static final BitSpec op = new ContinousBitSpec(31, 30, "op"); 889 private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2"); 890 private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3"); 891 private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf"); 892 private static final BitSpec opfLow = new ContinousBitSpec(10, 5, "opfLow"); 893 private static final BitSpec opfCC = new ContinousBitSpec(13, 11, "opfCC"); 894 private static final BitSpec opfCond = new ContinousBitSpec(17, 14, "opfCond"); 895 private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd"); 896 private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1"); 897 private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2"); 898 private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13"); 899 private static final BitSpec shcnt32 = new ContinousBitSpec(4, 0, "shcnt32"); 900 private static final BitSpec shcnt64 = new ContinousBitSpec(5, 0, "shcnt64"); 901 private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22"); 902 private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI"); 903 private static final BitSpec i = new ContinousBitSpec(13, 13, "i"); 904 private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19"); 905 private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22"); 906 private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30"); 907 private static final BitSpec a = new ContinousBitSpec(29, 29, "a"); 908 private static final BitSpec p = new ContinousBitSpec(19, 19, "p"); 909 private static final BitSpec x = new ContinousBitSpec(12, 12, "x"); 910 private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond"); 911 private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond"); 912 private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc"); 913 private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc"); 914 private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo"); 915 private static final BitSpec d16hi = new ContinousBitSpec(21, 20, true, "d16hi"); 916 private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo); 917 // Movcc 918 private static final BitSpec movccLo = new ContinousBitSpec(12, 11, "cc_lo"); 919 private static final BitSpec movccHi = new ContinousBitSpec(18, 18, "cc_hi"); 920 private static final BitSpec movccCond = new ContinousBitSpec(17, 14, "cond"); 921 private static final BitSpec simm11 = new ContinousBitSpec(10, 0, true, "simm11"); 922 923 // CBCond 924 private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo"); 925 private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi"); 926 private static final BitSpec c = new CompositeBitSpec(cHi, cLo); 927 private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond"); 928 private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2"); 929 private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo"); 930 private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, true, "d10Hi"); 931 private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo); 932 private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5"); 933 934 protected final boolean signExtend; 935 BitSpec(boolean signExtend)936 public BitSpec(boolean signExtend) { 937 super(); 938 this.signExtend = signExtend; 939 } 940 isSignExtend()941 public final boolean isSignExtend() { 942 return signExtend; 943 } 944 setBits(int word, int value)945 public abstract int setBits(int word, int value); 946 getBits(int word)947 public abstract int getBits(int word); 948 getWidth()949 public abstract int getWidth(); 950 valueFits(int value)951 public abstract boolean valueFits(int value); 952 } 953 954 public static final class ContinousBitSpec extends BitSpec { 955 private final int hiBit; 956 private final int lowBit; 957 private final int width; 958 private final int mask; 959 private final String name; 960 ContinousBitSpec(int hiBit, int lowBit, String name)961 public ContinousBitSpec(int hiBit, int lowBit, String name) { 962 this(hiBit, lowBit, false, name); 963 } 964 ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name)965 public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) { 966 super(signExt); 967 this.hiBit = hiBit; 968 this.lowBit = lowBit; 969 this.width = hiBit - lowBit + 1; 970 mask = ((1 << width) - 1) << lowBit; 971 this.name = name; 972 } 973 974 @Override setBits(int word, int value)975 public int setBits(int word, int value) { 976 assert valueFits(value) : String.format("Value 0x%x for field %s does not fit.", value, this); 977 return (word & ~mask) | ((value << lowBit) & mask); 978 } 979 980 @Override getBits(int word)981 public int getBits(int word) { 982 if (signExtend) { 983 return ((word & mask) << (31 - hiBit)) >> (32 - width); 984 } else { 985 return (word & mask) >>> lowBit; 986 } 987 } 988 989 @Override getWidth()990 public int getWidth() { 991 return width; 992 } 993 994 @Override toString()995 public String toString() { 996 return String.format("%s [%d:%d]", name, hiBit, lowBit); 997 } 998 999 @Override valueFits(int value)1000 public boolean valueFits(int value) { 1001 if (signExtend) { 1002 return isSimm(value, getWidth()); 1003 } else { 1004 return isImm(value, getWidth()); 1005 } 1006 } 1007 } 1008 1009 public static final class CompositeBitSpec extends BitSpec { 1010 private final BitSpec left; 1011 private final int leftWidth; 1012 private final BitSpec right; 1013 private final int rightWidth; 1014 private final int width; 1015 CompositeBitSpec(BitSpec left, BitSpec right)1016 public CompositeBitSpec(BitSpec left, BitSpec right) { 1017 super(left.isSignExtend()); 1018 assert !right.isSignExtend() : String.format("Right field %s must not be sign extended", right); 1019 this.left = left; 1020 this.leftWidth = left.getWidth(); 1021 this.right = right; 1022 this.rightWidth = right.getWidth(); 1023 this.width = leftWidth + rightWidth; 1024 } 1025 1026 @Override getBits(int word)1027 public int getBits(int word) { 1028 int l = left.getBits(word); 1029 int r = right.getBits(word); 1030 return (l << rightWidth) | r; 1031 } 1032 1033 @Override setBits(int word, int value)1034 public int setBits(int word, int value) { 1035 int l = leftBits(value); 1036 int r = rightBits(value); 1037 return left.setBits(right.setBits(word, r), l); 1038 } 1039 leftBits(int value)1040 private int leftBits(int value) { 1041 return getBits(value, width - 1, rightWidth, signExtend); 1042 } 1043 rightBits(int value)1044 private int rightBits(int value) { 1045 return getBits(value, rightWidth - 1, 0, false); 1046 } 1047 1048 @Override getWidth()1049 public int getWidth() { 1050 return width; 1051 } 1052 1053 @Override toString()1054 public String toString() { 1055 return String.format("CompositeBitSpec[%s, %s]", left, right); 1056 } 1057 1058 @Override valueFits(int value)1059 public boolean valueFits(int value) { 1060 int l = leftBits(value); 1061 int r = rightBits(value); 1062 return left.valueFits(l) && right.valueFits(r); 1063 } 1064 getBits(int inst, int hiBit, int lowBit, boolean signExtended)1065 private static int getBits(int inst, int hiBit, int lowBit, boolean signExtended) { 1066 int shifted = inst >> lowBit; 1067 if (signExtended) { 1068 return shifted; 1069 } else { 1070 return shifted & ((1 << (hiBit - lowBit + 1)) - 1); 1071 } 1072 } 1073 } 1074 1075 public static class BitKey { 1076 private final BitSpec spec; 1077 private final int value; 1078 BitKey(BitSpec spec, int value)1079 public BitKey(BitSpec spec, int value) { 1080 super(); 1081 this.spec = spec; 1082 this.value = value; 1083 } 1084 1085 @Override toString()1086 public String toString() { 1087 return String.format("BitKey %s=%s", spec, value); 1088 } 1089 } 1090 1091 /** 1092 * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp. 1093 */ 1094 public static final class BitKeyIndex { 1095 private final BitSpec spec; 1096 private final Map<Integer, BitKeyIndex> nodes; 1097 private SPARCOp op; 1098 BitKeyIndex(SPARCOp op)1099 public BitKeyIndex(SPARCOp op) { 1100 assert op != null; 1101 this.op = op; 1102 this.nodes = null; 1103 this.spec = null; 1104 } 1105 BitKeyIndex(BitSpec spec)1106 public BitKeyIndex(BitSpec spec) { 1107 assert spec != null; 1108 this.op = null; 1109 this.nodes = new HashMap<>(4); 1110 this.spec = spec; 1111 } 1112 1113 /** 1114 * Adds operation to the index. 1115 * 1116 * @param keys Ordered by the importance 1117 * @param operation Operation represented by this list of keys 1118 */ addOp(List<BitKey[]> keys, SPARCOp operation)1119 private void addOp(List<BitKey[]> keys, SPARCOp operation) { 1120 assert keys.size() > 0; 1121 BitKey[] firstKeys = keys.get(0); 1122 for (BitKey first : firstKeys) { 1123 assert first.spec.equals(spec) : first.spec + " " + spec; 1124 BitKeyIndex node; 1125 if (keys.size() == 1) { 1126 if (nodes.containsKey(first.value)) { 1127 node = nodes.get(first.value); 1128 assert node.op == null : node + " " + keys; 1129 node.op = operation; 1130 } else { 1131 assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value); 1132 node = new BitKeyIndex(operation); 1133 } 1134 } else { 1135 node = nodes.get(first.value); 1136 BitKey[] next = keys.get(1); 1137 if (node == null) { 1138 for (int i = 1; i < next.length; i++) { 1139 assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal"; 1140 } 1141 node = new BitKeyIndex(next[0].spec); 1142 } 1143 node.addOp(keys.subList(1, keys.size()), operation); 1144 } 1145 nodes.put(first.value, node); 1146 } 1147 } 1148 1149 /** 1150 * Finds the best matching {@link SPARCOp} for this instruction. 1151 */ find(int inst)1152 public SPARCOp find(int inst) { 1153 if (nodes != null) { 1154 int key = spec.getBits(inst); 1155 BitKeyIndex sub = nodes.get(key); 1156 if (sub == null) { 1157 if (op != null) { 1158 return op; 1159 } else { 1160 throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes)); 1161 } 1162 } 1163 return sub.find(inst); 1164 } else { 1165 return this.op; 1166 } 1167 } 1168 1169 @Override toString()1170 public String toString() { 1171 return this.op == null ? this.spec + ": " + this.nodes : this.op.toString(); 1172 } 1173 } 1174 1175 public static final Bpcc BPCC = new Bpcc(Op2s.Bp); 1176 public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp); 1177 public static final CBCond CBCOND = new CBCond(); 1178 public static final Bpr BPR = new Bpr(); 1179 public static final Br BR = new Br(); 1180 public static final Sethi SETHI = new Sethi(); 1181 public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc); 1182 public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc); 1183 public static final MOVicc MOVICC = new MOVicc(); 1184 public static final OpfOp OPF = new OpfOp(); 1185 public static final Op3Op OP3 = new Op3Op(); 1186 public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp); 1187 public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp); 1188 public static final SPARCOp CALL = new SPARCOp(Ops.CallOp); 1189 private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op); 1190 1191 static { 1192 for (SPARCOp op : SPARCOp.OPS) { op.getKeys()1193 INDEX.addOp(op.getKeys(), op); 1194 } 1195 } 1196 getSPARCOp(int inst)1197 public static SPARCOp getSPARCOp(int inst) { 1198 return INDEX.find(inst); 1199 } 1200 1201 /** 1202 * Represents a class of SPARC instruction and gives methods to modify its fields. 1203 */ 1204 public static class SPARCOp { 1205 private final Ops op; 1206 private final BitKey opKey; 1207 private List<BitKey[]> keyFields; 1208 private static final List<SPARCOp> OPS = new ArrayList<>(); 1209 SPARCOp(Ops op)1210 public SPARCOp(Ops op) { 1211 super(); 1212 this.op = op; 1213 this.opKey = new BitKey(BitSpec.op, op.value); 1214 OPS.add(this); 1215 } 1216 setBits(int word)1217 protected int setBits(int word) { 1218 return BitSpec.op.setBits(word, op.value); 1219 } 1220 match(int inst)1221 public boolean match(int inst) { 1222 for (BitKey[] keys : keyFields) { 1223 for (BitKey k : keys) { 1224 if (k.spec.getBits(inst) != k.value) { 1225 return false; 1226 } 1227 } 1228 } 1229 return true; 1230 } 1231 getKeys()1232 protected List<BitKey[]> getKeys() { 1233 if (keyFields == null) { 1234 keyFields = new ArrayList<>(4); 1235 keyFields.add(new BitKey[]{opKey}); 1236 } 1237 return keyFields; 1238 } 1239 getOp(int inst)1240 public Ops getOp(int inst) { 1241 return SPARCAssembler.OPS[BitSpec.op.getBits(inst)]; 1242 } 1243 1244 @Override toString()1245 public String toString() { 1246 String name = getClass().getName(); 1247 name = name.substring(name.lastIndexOf(".") + 1); 1248 return name + "[op: " + op + "]"; 1249 } 1250 } 1251 1252 /** 1253 * Base class for control transfer operations; provides access to the disp field. 1254 */ 1255 public abstract static class ControlTransferOp extends SPARCOp { 1256 private final Op2s op2; 1257 private final boolean delaySlot; 1258 private final BitSpec disp; 1259 private final BitKey[] op2Key; 1260 ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp)1261 private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) { 1262 super(op); 1263 this.op2 = op2; 1264 this.delaySlot = delaySlot; 1265 this.disp = disp; 1266 this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)}; 1267 } 1268 hasDelaySlot()1269 public boolean hasDelaySlot() { 1270 return delaySlot; 1271 } 1272 1273 @Override setBits(int word)1274 protected int setBits(int word) { 1275 return BitSpec.op2.setBits(super.setBits(word), op2.value); 1276 } 1277 setDisp(int inst, SPARCMacroAssembler masm, Label lab)1278 protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) { 1279 if (lab.isBound()) { 1280 int d = (lab.position() - masm.position()) / 4; 1281 return setDisp(inst, d); 1282 } else { 1283 masm.patchUnbound(lab); 1284 return inst; 1285 } 1286 } 1287 setDisp(int inst, int d)1288 public int setDisp(int inst, int d) { 1289 assert this.match(inst); 1290 if (!isValidDisp(d)) { 1291 throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this); 1292 } 1293 return this.disp.setBits(inst, d); 1294 } 1295 isValidDisp(int d)1296 public boolean isValidDisp(int d) { 1297 return this.disp.valueFits(d); 1298 } 1299 setAnnul(int inst, boolean a)1300 public int setAnnul(int inst, boolean a) { 1301 return BitSpec.a.setBits(inst, a ? 1 : 0); 1302 } 1303 1304 @Override getKeys()1305 protected List<BitKey[]> getKeys() { 1306 List<BitKey[]> keys = super.getKeys(); 1307 keys.add(op2Key); 1308 return keys; 1309 } 1310 getDisp(int inst)1311 public int getDisp(int inst) { 1312 return this.disp.getBits(inst); 1313 } 1314 isAnnulable(int inst)1315 public abstract boolean isAnnulable(int inst); 1316 isConditional(int inst)1317 public abstract boolean isConditional(int inst); 1318 } 1319 1320 public static final class Bpcc extends ControlTransferOp { Bpcc(Op2s op2)1321 public Bpcc(Op2s op2) { 1322 super(Ops.BranchOp, op2, true, BitSpec.disp19); 1323 } 1324 emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab)1325 public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) { 1326 int inst = setBits(0); 1327 inst = BitSpec.a.setBits(inst, annul.flag); 1328 inst = BitSpec.cond.setBits(inst, cf.value); 1329 inst = BitSpec.cc.setBits(inst, cc.value); 1330 inst = BitSpec.p.setBits(inst, p.flag); 1331 masm.insertNopAfterCBCond(); 1332 masm.emitInt(setDisp(inst, masm, lab)); 1333 } 1334 1335 @Override isAnnulable(int inst)1336 public boolean isAnnulable(int inst) { 1337 return isConditional(inst); 1338 } 1339 1340 @Override isConditional(int inst)1341 public boolean isConditional(int inst) { 1342 int cond = BitSpec.cond.getBits(inst); 1343 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1344 } 1345 } 1346 1347 public static final class Br extends ControlTransferOp { Br()1348 public Br() { 1349 super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22); 1350 } 1351 1352 @Override isAnnulable(int inst)1353 public boolean isAnnulable(int inst) { 1354 return isConditional(inst); 1355 } 1356 1357 @Override isConditional(int inst)1358 public boolean isConditional(int inst) { 1359 int cond = BitSpec.cond.getBits(inst); 1360 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1361 } 1362 emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab)1363 public void emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab) { 1364 int inst = setBits(0); 1365 inst = BitSpec.cond.setBits(inst, cond.value); 1366 inst = BitSpec.a.setBits(inst, a.flag); 1367 masm.insertNopAfterCBCond(); 1368 masm.emitInt(setDisp(inst, masm, lab)); 1369 } 1370 } 1371 1372 public static final class Bpr extends ControlTransferOp { 1373 private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0); 1374 Bpr()1375 public Bpr() { 1376 super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16); 1377 } 1378 emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab)1379 public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) { 1380 int inst = setBits(0); 1381 inst = BitSpec.rcond.setBits(inst, rcond.value); 1382 inst = BitSpec.a.setBits(inst, a.flag); 1383 inst = BitSpec.p.setBits(inst, p.flag); 1384 inst = BitSpec.rs1.setBits(inst, rs1.encoding); 1385 masm.insertNopAfterCBCond(); 1386 masm.emitInt(setDisp(inst, masm, lab)); 1387 } 1388 1389 @Override getKeys()1390 protected List<BitKey[]> getKeys() { 1391 List<BitKey[]> keys = super.getKeys(); 1392 keys.add(new BitKey[]{CBCOND_KEY}); 1393 return keys; 1394 } 1395 1396 @Override isAnnulable(int inst)1397 public boolean isAnnulable(int inst) { 1398 return isConditional(inst); 1399 } 1400 1401 @Override isConditional(int inst)1402 public boolean isConditional(int inst) { 1403 int cond = BitSpec.cond.getBits(inst); 1404 return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; 1405 } 1406 } 1407 1408 public static final class CBCond extends ControlTransferOp { 1409 private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1); 1410 CBCond()1411 private CBCond() { 1412 super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10); 1413 } 1414 1415 @Override getKeys()1416 protected List<BitKey[]> getKeys() { 1417 List<BitKey[]> keys = super.getKeys(); 1418 keys.add(new BitKey[]{CBCOND_KEY}); 1419 return keys; 1420 } 1421 emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab)1422 public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) { 1423 int inst = setBits(0, cf, cc2, rs1); 1424 inst = BitSpec.rs2.setBits(inst, rs2.encoding); 1425 inst = BitSpec.i.setBits(inst, 0); 1426 masm.insertNopAfterCBCond(); 1427 emit(masm, lab, inst); 1428 } 1429 emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab)1430 public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) { 1431 int inst = setBits(0, cf, cc2, rs1); 1432 inst = BitSpec.simm5.setBits(inst, simm5); 1433 inst = BitSpec.i.setBits(inst, 1); 1434 emit(masm, lab, inst); 1435 } 1436 emit(SPARCMacroAssembler masm, Label lab, int baseInst)1437 private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) { 1438 int inst = baseInst; 1439 masm.insertNopAfterCBCond(); 1440 masm.emitInt(setDisp(inst, masm, lab)); 1441 } 1442 setBits(int base, ConditionFlag cf, boolean cc2, Register rs1)1443 private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) { 1444 int inst = super.setBits(base); 1445 inst = BitSpec.rs1.setBits(inst, rs1.encoding); 1446 inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0); 1447 inst = BitSpec.c.setBits(inst, cf.value); 1448 return BitSpec.cbcond.setBits(inst, 1); 1449 } 1450 1451 @Override isAnnulable(int inst)1452 public boolean isAnnulable(int inst) { 1453 return false; 1454 } 1455 1456 @Override isConditional(int inst)1457 public boolean isConditional(int inst) { 1458 return true; 1459 } 1460 } 1461 1462 public static class Op2Op extends SPARCOp { 1463 private final Op2s op2; 1464 private final BitKey op2Key; 1465 Op2Op(Ops op, Op2s op2)1466 public Op2Op(Ops op, Op2s op2) { 1467 super(op); 1468 this.op2 = op2; 1469 op2Key = new BitKey(BitSpec.op2, op2.value); 1470 } 1471 1472 @Override setBits(int word)1473 protected int setBits(int word) { 1474 int result = super.setBits(word); 1475 return BitSpec.op2.setBits(result, op2.value); 1476 } 1477 1478 @Override getKeys()1479 protected List<BitKey[]> getKeys() { 1480 List<BitKey[]> keys = super.getKeys(); 1481 keys.add(new BitKey[]{op2Key}); 1482 return keys; 1483 } 1484 } 1485 1486 public static final class Sethi extends Op2Op { Sethi()1487 public Sethi() { 1488 super(Ops.BranchOp, Op2s.Sethi); 1489 } 1490 getRS1(int word)1491 public static Register getRS1(int word) { 1492 int regNum = BitSpec.rs1.getBits(word); 1493 return SPARC.cpuRegisters.get(regNum); 1494 } 1495 getImm22(int word)1496 public static int getImm22(int word) { 1497 return BitSpec.imm22.getBits(word); 1498 } 1499 isNop(int inst)1500 public static boolean isNop(int inst) { 1501 return getRS1(inst).equals(g0) && getImm22(inst) == 0; 1502 } 1503 } 1504 1505 public static final class Op3Op extends SPARCOp { Op3Op()1506 public Op3Op() { 1507 super(ArithOp); 1508 } 1509 getOp3(int inst)1510 public Op3s getOp3(int inst) { 1511 assert match(inst); 1512 return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)]; 1513 } 1514 emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd)1515 public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) { 1516 int instruction = setBits(0, opcode, rs1, rd); 1517 instruction = BitSpec.rs2.setBits(instruction, rs2.encoding); 1518 instruction = BitSpec.i.setBits(instruction, 0); 1519 masm.emitInt(instruction); 1520 } 1521 emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd)1522 public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) { 1523 int instruction = setBits(0, opcode, rs1, rd); 1524 instruction = BitSpec.i.setBits(instruction, 1); 1525 BitSpec immediateSpec; 1526 switch (opcode) { 1527 case Sllx: 1528 case Srlx: 1529 case Srax: 1530 immediateSpec = BitSpec.shcnt64; 1531 break; 1532 case Sll: 1533 case Srl: 1534 case Sra: 1535 immediateSpec = BitSpec.shcnt32; 1536 break; 1537 default: 1538 immediateSpec = BitSpec.simm13; 1539 break; 1540 } 1541 instruction = immediateSpec.setBits(instruction, simm13); 1542 masm.emitInt(instruction); 1543 } 1544 setBits(int instruction, Op3s op3, Register rs1, Register rd)1545 private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) { 1546 assert op3.op.equals(ArithOp); 1547 int tmp = BitSpec.op3.setBits(instruction, op3.value); 1548 switch (op3) { 1549 case Sllx: 1550 case Srlx: 1551 case Srax: 1552 tmp = BitSpec.x.setBits(tmp, 1); 1553 break; 1554 } 1555 tmp = BitSpec.op.setBits(tmp, op3.op.value); 1556 tmp = BitSpec.rd.setBits(tmp, rd.encoding); 1557 return BitSpec.rs1.setBits(tmp, rs1.encoding); 1558 } 1559 } 1560 1561 /** 1562 * Used for interfacing FP and GP conditional move instructions. 1563 */ 1564 public interface CMOV { emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1565 void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd); 1566 emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1567 void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd); 1568 } 1569 1570 public static final class MOVicc extends SPARCOp implements CMOV { 1571 private static final Op3s op3 = Movcc; 1572 MOVicc()1573 public MOVicc() { 1574 super(ArithOp); 1575 } 1576 1577 @Override emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1578 public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) { 1579 int inst = setBits(0, condition, cc, rd); 1580 inst = BitSpec.rs2.setBits(inst, rs2.encoding()); 1581 masm.emitInt(inst); 1582 } 1583 1584 @Override emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1585 public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) { 1586 int inst = setBits(0, condition, cc, rd); 1587 inst = BitSpec.i.setBits(inst, 1); 1588 inst = BitSpec.simm11.setBits(inst, simm11); 1589 masm.emitInt(inst); 1590 } 1591 setBits(int word, ConditionFlag condition, CC cc, Register rd)1592 protected int setBits(int word, ConditionFlag condition, CC cc, Register rd) { 1593 int inst = super.setBits(word); 1594 inst = BitSpec.rd.setBits(inst, rd.encoding()); 1595 inst = BitSpec.op3.setBits(inst, op3.value); 1596 inst = BitSpec.movccCond.setBits(inst, condition.value); 1597 inst = BitSpec.movccLo.setBits(inst, cc.value); 1598 return BitSpec.movccHi.setBits(inst, cc.isFloat ? 0 : 1); 1599 } 1600 1601 @Override getKeys()1602 protected List<BitKey[]> getKeys() { 1603 List<BitKey[]> keys = super.getKeys(); 1604 keys.add(new BitKey[]{new BitKey(BitSpec.op3, op3.value)}); 1605 return keys; 1606 } 1607 } 1608 1609 public static final class FMOVcc extends SPARCOp implements CMOV { 1610 private OpfLow opfLow; 1611 FMOVcc(OpfLow opfLow)1612 public FMOVcc(OpfLow opfLow) { 1613 super(ArithOp); 1614 this.opfLow = opfLow; 1615 } 1616 1617 @Override emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1618 public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) { 1619 int inst = setBits(0); 1620 inst = BitSpec.rd.setBits(inst, rd.encoding()); 1621 inst = BitSpec.op3.setBits(inst, opfLow.op3.value); 1622 inst = BitSpec.opfCond.setBits(inst, condition.value); 1623 inst = BitSpec.opfCC.setBits(inst, cc.getOpfCCValue()); 1624 inst = BitSpec.opfLow.setBits(inst, opfLow.value); 1625 inst = BitSpec.rs2.setBits(inst, rs2.encoding()); 1626 masm.emitInt(inst); 1627 } 1628 1629 @Override emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1630 public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) { 1631 throw new IllegalArgumentException("FMOVCC cannot be used with immediate value"); 1632 } 1633 1634 @Override getKeys()1635 protected List<BitKey[]> getKeys() { 1636 List<BitKey[]> keys = super.getKeys(); 1637 keys.add(new BitKey[]{new BitKey(BitSpec.op3, opfLow.op3.value)}); 1638 keys.add(new BitKey[]{new BitKey(BitSpec.opfLow, opfLow.value)}); 1639 return keys; 1640 } 1641 } 1642 1643 public static final class OpfOp extends SPARCOp { 1644 1645 private BitKey[] op3Keys; 1646 OpfOp(BitKey... op3Keys)1647 public OpfOp(BitKey... op3Keys) { 1648 super(ArithOp); 1649 this.op3Keys = op3Keys; 1650 } 1651 OpfOp()1652 public OpfOp() { 1653 // @formatter:off 1654 this(new BitKey[]{ 1655 new BitKey(BitSpec.op3, Op3s.Fpop1.value), 1656 new BitKey(BitSpec.op3, Op3s.Fpop2.value), 1657 new BitKey(BitSpec.op3, Op3s.Impdep1.value), 1658 new BitKey(BitSpec.op3, Op3s.Impdep2.value)}); 1659 // @formatter:on 1660 } 1661 emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd)1662 public static void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) { 1663 int instruction = setBits(0, opf, rs1, rs2); 1664 instruction = BitSpec.rd.setBits(instruction, rd.encoding); 1665 instruction = BitSpec.i.setBits(instruction, 0); 1666 masm.emitInt(instruction); 1667 } 1668 emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2)1669 public static void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) { 1670 assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf; 1671 int instruction = setBits(0, opf, rs1, rs2); 1672 instruction = BitSpec.fcc.setBits(instruction, cc.value); 1673 masm.emitInt(instruction); 1674 } 1675 setBits(int instruction, Opfs opf, Register rs1, Register rs2)1676 private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) { 1677 int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value); 1678 tmp = BitSpec.op3.setBits(tmp, opf.op3.value); 1679 tmp = BitSpec.opf.setBits(tmp, opf.value); 1680 tmp = BitSpec.rs1.setBits(tmp, rs1.encoding); 1681 return BitSpec.rs2.setBits(tmp, rs2.encoding); 1682 } 1683 1684 @Override getKeys()1685 protected List<BitKey[]> getKeys() { 1686 List<BitKey[]> keys = super.getKeys(); 1687 keys.add(op3Keys); 1688 // @formatter:on 1689 return keys; 1690 } 1691 } 1692 isCPURegister(Register... regs)1693 public static boolean isCPURegister(Register... regs) { 1694 for (Register reg : regs) { 1695 if (!isCPURegister(reg)) { 1696 return false; 1697 } 1698 } 1699 return true; 1700 } 1701 isCPURegister(Register r)1702 public static boolean isCPURegister(Register r) { 1703 return r.getRegisterCategory().equals(CPU); 1704 } 1705 isGlobalRegister(Register r)1706 public static boolean isGlobalRegister(Register r) { 1707 return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number; 1708 } 1709 isSingleFloatRegister(Register r)1710 public static boolean isSingleFloatRegister(Register r) { 1711 return r.getRegisterCategory().equals(FPUs); 1712 } 1713 isDoubleFloatRegister(Register r)1714 public static boolean isDoubleFloatRegister(Register r) { 1715 return r.getRegisterCategory().equals(FPUd); 1716 } 1717 hasFeature(CPUFeature feature)1718 public boolean hasFeature(CPUFeature feature) { 1719 return ((SPARC) this.target.arch).features.contains(feature); 1720 } 1721 simm(int x, int nbits)1722 public static final int simm(int x, int nbits) { 1723 // assert_signed_range(x, nbits); 1724 return x & ((1 << nbits) - 1); 1725 } 1726 isImm(int x, int nbits)1727 public static final boolean isImm(int x, int nbits) { 1728 // assert_signed_range(x, nbits); 1729 return simm(x, nbits) == x; 1730 } 1731 1732 /** 1733 * Minimum value for signed immediate ranges. 1734 */ minSimm(long nbits)1735 public static long minSimm(long nbits) { 1736 return -(1L << (nbits - 1)); 1737 } 1738 1739 /** 1740 * Maximum value for signed immediate ranges. 1741 */ maxSimm(long nbits)1742 public static long maxSimm(long nbits) { 1743 return (1L << (nbits - 1)) - 1; 1744 } 1745 1746 /** 1747 * Test if imm is within signed immediate range for nbits. 1748 */ isSimm(long imm, int nbits)1749 public static boolean isSimm(long imm, int nbits) { 1750 return minSimm(nbits) <= imm && imm <= maxSimm(nbits); 1751 } 1752 isSimm10(long imm)1753 public static boolean isSimm10(long imm) { 1754 return isSimm(imm, 10); 1755 } 1756 isSimm11(long imm)1757 public static boolean isSimm11(long imm) { 1758 return isSimm(imm, 11); 1759 } 1760 isSimm11(JavaConstant constant)1761 public static boolean isSimm11(JavaConstant constant) { 1762 return constant.isNull() || isSimm11(constant.asLong()); 1763 } 1764 isSimm5(JavaConstant constant)1765 public static boolean isSimm5(JavaConstant constant) { 1766 return constant.isNull() || isSimm(constant.asLong(), 5); 1767 } 1768 isSimm5(long imm)1769 public static boolean isSimm5(long imm) { 1770 return isSimm(imm, 5); 1771 } 1772 isSimm13(int imm)1773 public static boolean isSimm13(int imm) { 1774 return isSimm(imm, 13); 1775 } 1776 isSimm13(JavaConstant constant)1777 public static boolean isSimm13(JavaConstant constant) { 1778 long bits; 1779 switch (constant.getJavaKind()) { 1780 case Double: 1781 bits = Double.doubleToRawLongBits(constant.asDouble()); 1782 break; 1783 case Float: 1784 bits = Float.floatToRawIntBits(constant.asFloat()); 1785 break; 1786 case Object: 1787 return constant.isNull(); 1788 default: 1789 bits = constant.asLong(); 1790 break; 1791 } 1792 return constant.isNull() || isSimm13(bits); 1793 } 1794 isSimm13(long imm)1795 public static boolean isSimm13(long imm) { 1796 return NumUtil.isInt(imm) && isSimm(imm, 13); 1797 } 1798 isWordDisp30(long imm)1799 public static boolean isWordDisp30(long imm) { 1800 return isSimm(imm, 30 + 2); 1801 } 1802 hi22(int x)1803 public static final int hi22(int x) { 1804 return x >>> 10; 1805 } 1806 lo10(int x)1807 public static final int lo10(int x) { 1808 return x & ((1 << 10) - 1); 1809 } 1810 1811 // @formatter:off 1812 /** 1813 * Instruction format for Fmt00 instructions. This abstraction is needed as it 1814 * makes the patching easier later on. 1815 * <pre> 1816 * | 00 | a | op2 | b | 1817 * |31 30|29 25|24 22|21 0| 1818 * </pre> 1819 */ 1820 // @formatter:on fmt00(int a, int op2, int b)1821 protected void fmt00(int a, int op2, int b) { 1822 assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b); 1823 int word = 0; 1824 BitSpec.op.setBits(word, 0); 1825 BitSpec.rd.setBits(word, a); 1826 BitSpec.op2.setBits(word, op2); 1827 BitSpec.imm22.setBits(word, b); 1828 emitInt(a << 25 | op2 << 22 | b); 1829 } 1830 op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd)1831 private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) { 1832 int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding); 1833 fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b); 1834 } 1835 op3(Op3s op3, Register rs1, Register rs2, Register rd)1836 protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) { 1837 int b = rs2 == null ? 0 : rs2.encoding; 1838 int xBit = getXBit(op3); 1839 fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit); 1840 } 1841 op3(Op3s op3, Register rs1, int simm13, Register rd)1842 protected void op3(Op3s op3, Register rs1, int simm13, Register rd) { 1843 assert isSimm13(simm13) : simm13; 1844 int i = 1 << 13; 1845 int simm13WithX = simm13 | getXBit(op3); 1846 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1)); 1847 } 1848 insertNopAfterCBCond()1849 public void insertNopAfterCBCond() { 1850 int pos = position() - INSTRUCTION_SIZE; 1851 if (pos == 0) { 1852 return; 1853 } 1854 int inst = getInt(pos); 1855 if (CBCOND.match(inst)) { 1856 nop(); 1857 } 1858 } 1859 patchUnbound(Label label)1860 protected int patchUnbound(Label label) { 1861 label.addPatchAt(position(), this); 1862 return 0; 1863 } 1864 1865 // @formatter:off 1866 /** 1867 * NOP. 1868 * <pre> 1869 * | 00 |00000| 100 | 0 | 1870 * |31 30|29 25|24 22|21 0| 1871 * </pre> 1872 */ 1873 // @formatter:on nop()1874 public void nop() { 1875 emitInt(1 << 24); 1876 } 1877 sethi(int imm22, Register dst)1878 public void sethi(int imm22, Register dst) { 1879 fmt00(dst.encoding, Op2s.Sethi.value, imm22); 1880 } 1881 1882 // @formatter:off 1883 /** 1884 * Instruction format for calls. 1885 * <pre> 1886 * | 01 | disp30 | 1887 * |31 30|29 0| 1888 * </pre> 1889 * 1890 * @return Position of the call instruction 1891 */ 1892 // @formatter:on call(int disp30)1893 public int call(int disp30) { 1894 assert isImm(disp30, 30); 1895 insertNopAfterCBCond(); 1896 int before = position(); 1897 int instr = 1 << 30; 1898 instr |= disp30; 1899 emitInt(instr); 1900 return before; 1901 } 1902 add(Register rs1, Register rs2, Register rd)1903 public void add(Register rs1, Register rs2, Register rd) { 1904 op3(Add, rs1, rs2, rd); 1905 } 1906 add(Register rs1, int simm13, Register rd)1907 public void add(Register rs1, int simm13, Register rd) { 1908 op3(Add, rs1, simm13, rd); 1909 } 1910 addc(Register rs1, Register rs2, Register rd)1911 public void addc(Register rs1, Register rs2, Register rd) { 1912 op3(Addc, rs1, rs2, rd); 1913 } 1914 addc(Register rs1, int simm13, Register rd)1915 public void addc(Register rs1, int simm13, Register rd) { 1916 op3(Addc, rs1, simm13, rd); 1917 } 1918 addcc(Register rs1, Register rs2, Register rd)1919 public void addcc(Register rs1, Register rs2, Register rd) { 1920 op3(Addcc, rs1, rs2, rd); 1921 } 1922 addcc(Register rs1, int simm13, Register rd)1923 public void addcc(Register rs1, int simm13, Register rd) { 1924 op3(Addcc, rs1, simm13, rd); 1925 } 1926 and(Register rs1, Register rs2, Register rd)1927 public void and(Register rs1, Register rs2, Register rd) { 1928 op3(And, rs1, rs2, rd); 1929 } 1930 and(Register rs1, int simm13, Register rd)1931 public void and(Register rs1, int simm13, Register rd) { 1932 op3(And, rs1, simm13, rd); 1933 } 1934 andcc(Register rs1, Register rs2, Register rd)1935 public void andcc(Register rs1, Register rs2, Register rd) { 1936 op3(Andcc, rs1, rs2, rd); 1937 } 1938 andcc(Register rs1, int simm13, Register rd)1939 public void andcc(Register rs1, int simm13, Register rd) { 1940 op3(Andcc, rs1, simm13, rd); 1941 } 1942 andn(Register rs1, Register rs2, Register rd)1943 public void andn(Register rs1, Register rs2, Register rd) { 1944 op3(Andn, rs1, rs2, rd); 1945 } 1946 andn(Register rs1, int simm13, Register rd)1947 public void andn(Register rs1, int simm13, Register rd) { 1948 op3(Andn, rs1, simm13, rd); 1949 } 1950 andncc(Register rs1, Register rs2, Register rd)1951 public void andncc(Register rs1, Register rs2, Register rd) { 1952 op3(Andncc, rs1, rs2, rd); 1953 } 1954 andncc(Register rs1, int simm13, Register rd)1955 public void andncc(Register rs1, int simm13, Register rd) { 1956 op3(Andncc, rs1, simm13, rd); 1957 } 1958 movwtos(Register rs2, Register rd)1959 public void movwtos(Register rs2, Register rd) { 1960 assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd); 1961 op3(Impdep1, Movwtos, null, rs2, rd); 1962 } 1963 umulxhi(Register rs1, Register rs2, Register rd)1964 public void umulxhi(Register rs1, Register rs2, Register rd) { 1965 op3(Impdep1, UMulxhi, rs1, rs2, rd); 1966 } 1967 fdtos(Register rs2, Register rd)1968 public void fdtos(Register rs2, Register rd) { 1969 assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd); 1970 op3(Fpop1, Fdtos, null, rs2, rd); 1971 } 1972 movstouw(Register rs2, Register rd)1973 public void movstouw(Register rs2, Register rd) { 1974 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1975 op3(Impdep1, Movstosw, null, rs2, rd); 1976 } 1977 movstosw(Register rs2, Register rd)1978 public void movstosw(Register rs2, Register rd) { 1979 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1980 op3(Impdep1, Movstosw, null, rs2, rd); 1981 } 1982 movdtox(Register rs2, Register rd)1983 public void movdtox(Register rs2, Register rd) { 1984 assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); 1985 op3(Impdep1, Movdtox, null, rs2, rd); 1986 } 1987 movxtod(Register rs2, Register rd)1988 public void movxtod(Register rs2, Register rd) { 1989 assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd); 1990 op3(Impdep1, Movxtod, null, rs2, rd); 1991 } 1992 fadds(Register rs1, Register rs2, Register rd)1993 public void fadds(Register rs1, Register rs2, Register rd) { 1994 op3(Fpop1, Fadds, rs1, rs2, rd); 1995 } 1996 faddd(Register rs1, Register rs2, Register rd)1997 public void faddd(Register rs1, Register rs2, Register rd) { 1998 op3(Fpop1, Faddd, rs1, rs2, rd); 1999 } 2000 fdivs(Register rs1, Register rs2, Register rd)2001 public void fdivs(Register rs1, Register rs2, Register rd) { 2002 op3(Fpop1, Fdivs, rs1, rs2, rd); 2003 } 2004 fdivd(Register rs1, Register rs2, Register rd)2005 public void fdivd(Register rs1, Register rs2, Register rd) { 2006 op3(Fpop1, Fdivd, rs1, rs2, rd); 2007 } 2008 fmovs(Register rs2, Register rd)2009 public void fmovs(Register rs2, Register rd) { 2010 op3(Fpop1, Fmovs, null, rs2, rd); 2011 } 2012 fmovd(Register rs2, Register rd)2013 public void fmovd(Register rs2, Register rd) { 2014 op3(Fpop1, Fmovd, null, rs2, rd); 2015 } 2016 fsrc2s(Register rs2, Register rd)2017 public void fsrc2s(Register rs2, Register rd) { 2018 op3(Impdep1, Fsrc2s, null, rs2, rd); 2019 } 2020 fsrc2d(Register rs2, Register rd)2021 public void fsrc2d(Register rs2, Register rd) { 2022 op3(Impdep1, Fsrc2d, null, rs2, rd); 2023 } 2024 fmuls(Register rs1, Register rs2, Register rd)2025 public void fmuls(Register rs1, Register rs2, Register rd) { 2026 op3(Fpop1, Fmuls, rs1, rs2, rd); 2027 } 2028 fsmuld(Register rs1, Register rs2, Register rd)2029 public void fsmuld(Register rs1, Register rs2, Register rd) { 2030 op3(Fpop1, Fsmuld, rs1, rs2, rd); 2031 } 2032 fmuld(Register rs1, Register rs2, Register rd)2033 public void fmuld(Register rs1, Register rs2, Register rd) { 2034 op3(Fpop1, Fmuld, rs1, rs2, rd); 2035 } 2036 fnegs(Register rs2, Register rd)2037 public void fnegs(Register rs2, Register rd) { 2038 op3(Fpop1, Fnegs, null, rs2, rd); 2039 } 2040 fnegd(Register rs2, Register rd)2041 public void fnegd(Register rs2, Register rd) { 2042 op3(Fpop1, Fnegd, null, rs2, rd); 2043 } 2044 2045 /** 2046 * Helper method to determine if the instruction needs the X bit set. 2047 */ getXBit(Op3s op3)2048 private static int getXBit(Op3s op3) { 2049 switch (op3) { 2050 case Sllx: 2051 case Srax: 2052 case Srlx: 2053 return 1 << 12; 2054 default: 2055 return 0; 2056 } 2057 } 2058 fstoi(Register rs2, Register rd)2059 public void fstoi(Register rs2, Register rd) { 2060 op3(Fpop1, Fstoi, null, rs2, rd); 2061 } 2062 fstox(Register rs2, Register rd)2063 public void fstox(Register rs2, Register rd) { 2064 op3(Fpop1, Fstox, null, rs2, rd); 2065 } 2066 fdtox(Register rs2, Register rd)2067 public void fdtox(Register rs2, Register rd) { 2068 op3(Fpop1, Fdtox, null, rs2, rd); 2069 } 2070 fstod(Register rs2, Register rd)2071 public void fstod(Register rs2, Register rd) { 2072 op3(Fpop1, Fstod, null, rs2, rd); 2073 } 2074 fdtoi(Register rs2, Register rd)2075 public void fdtoi(Register rs2, Register rd) { 2076 op3(Fpop1, Fdtoi, null, rs2, rd); 2077 } 2078 fitos(Register rs2, Register rd)2079 public void fitos(Register rs2, Register rd) { 2080 op3(Fpop1, Fitos, null, rs2, rd); 2081 } 2082 fitod(Register rs2, Register rd)2083 public void fitod(Register rs2, Register rd) { 2084 op3(Fpop1, Fitod, null, rs2, rd); 2085 } 2086 fxtos(Register rs2, Register rd)2087 public void fxtos(Register rs2, Register rd) { 2088 op3(Fpop1, Fxtos, null, rs2, rd); 2089 } 2090 fxtod(Register rs2, Register rd)2091 public void fxtod(Register rs2, Register rd) { 2092 op3(Fpop1, Fxtod, null, rs2, rd); 2093 } 2094 fzeros(Register rd)2095 public void fzeros(Register rd) { 2096 op3(Impdep1, Fzeros, null, null, rd); 2097 } 2098 fzerod(Register rd)2099 public void fzerod(Register rd) { 2100 op3(Impdep1, Fzerod, null, null, rd); 2101 } 2102 flushw()2103 public void flushw() { 2104 op3(Flushw, g0, g0, g0); 2105 } 2106 fsqrtd(Register rs2, Register rd)2107 public void fsqrtd(Register rs2, Register rd) { 2108 op3(Fpop1, Fsqrtd, null, rs2, rd); 2109 } 2110 fsqrts(Register rs2, Register rd)2111 public void fsqrts(Register rs2, Register rd) { 2112 op3(Fpop1, Fsqrts, null, rs2, rd); 2113 } 2114 fabss(Register rs2, Register rd)2115 public void fabss(Register rs2, Register rd) { 2116 op3(Fpop1, Fabss, null, rs2, rd); 2117 } 2118 fabsd(Register rs2, Register rd)2119 public void fabsd(Register rs2, Register rd) { 2120 op3(Fpop1, Fabsd, null, rs2, rd); 2121 } 2122 fsubs(Register rs1, Register rs2, Register rd)2123 public void fsubs(Register rs1, Register rs2, Register rd) { 2124 op3(Fpop1, Fsubs, rs1, rs2, rd); 2125 } 2126 fsubd(Register rs1, Register rs2, Register rd)2127 public void fsubd(Register rs1, Register rs2, Register rd) { 2128 op3(Fpop1, Fsubd, rs1, rs2, rd); 2129 } 2130 2131 // @formatter:off 2132 /** 2133 * Instruction format for fcmp. 2134 * <pre> 2135 * | 10 | --- |cc1|cc0|desc | rs1 | opf | rs2 | 2136 * |31 30|29 27|26 |25 |24 19|18 14|13 5|4 0| 2137 * </pre> 2138 */ 2139 // @formatter:on fcmp(CC cc, Opfs opf, Register rs1, Register rs2)2140 public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) { 2141 int a = cc.value; 2142 int b = opf.value << 5 | rs2.encoding; 2143 delaySlotOptimizationPoints.add(position()); 2144 fmt10(a, Fpop2.value, rs1.encoding, b); 2145 } 2146 2147 // @formatter:off 2148 /** 2149 * Instruction format for most arithmetic stuff. 2150 * <pre> 2151 * | 10 | rd | op3 | rs1 | b | 2152 * |31 30|29 25|24 19|18 14|13 0| 2153 * </pre> 2154 */ 2155 // @formatter:on fmt10(int rd, int op3, int rs1, int b)2156 protected void fmt10(int rd, int op3, int rs1, int b) { 2157 fmt(0b10, rd, op3, rs1, b); 2158 } 2159 2160 // @formatter:off 2161 /** 2162 * Instruction format for most arithmetic stuff. 2163 * <pre> 2164 * | op | rd | op3 | rs1 | b | 2165 * |31 30|29 25|24 19|18 14|13 0| 2166 * </pre> 2167 */ 2168 // @formatter:on fmt(int op, int rd, int op3, int rs1, int b)2169 protected void fmt(int op, int rd, int op3, int rs1, int b) { 2170 assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b); 2171 int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b; 2172 emitInt(instr); 2173 } 2174 illtrap(int const22)2175 public void illtrap(int const22) { 2176 fmt00(0, Op2s.Illtrap.value, const22); 2177 } 2178 jmpl(Register rs1, Register rs2, Register rd)2179 public void jmpl(Register rs1, Register rs2, Register rd) { 2180 insertNopAfterCBCond(); 2181 op3(Jmpl, rs1, rs2, rd); 2182 } 2183 2184 /** 2185 * @return Position of the jmpl instruction 2186 */ jmpl(Register rs1, int simm13, Register rd)2187 public int jmpl(Register rs1, int simm13, Register rd) { 2188 insertNopAfterCBCond(); 2189 int before = position(); 2190 op3(Jmpl, rs1, simm13, rd); 2191 return before; 2192 } 2193 fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd)2194 public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) { 2195 fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value); 2196 } 2197 fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd)2198 public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) { 2199 fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value); 2200 } 2201 fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow)2202 private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) { 2203 int opfCC = cc.getOpfCCValue(); 2204 int a = opfCC << 11 | opfLow << 5 | rs2.encoding; 2205 fmt10(rd.encoding, Fpop2.value, cond.value, a); 2206 } 2207 movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd)2208 public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) { 2209 movcc(conditionFlag, cc, 0, rs2.encoding, rd); 2210 } 2211 movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd)2212 public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) { 2213 assert isSimm11(simm11); 2214 movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd); 2215 } 2216 movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd)2217 private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) { 2218 int cc01 = 0b11 & cc.value; 2219 int cc2 = cc.isFloat ? 0 : 1; 2220 int a = cc2 << 4 | conditionFlag.value; 2221 int b = cc01 << 11 | i << 13 | imm; 2222 fmt10(rd.encoding, Movcc.value, a, b); 2223 } 2224 mulx(Register rs1, Register rs2, Register rd)2225 public void mulx(Register rs1, Register rs2, Register rd) { 2226 op3(Mulx, rs1, rs2, rd); 2227 } 2228 mulx(Register rs1, int simm13, Register rd)2229 public void mulx(Register rs1, int simm13, Register rd) { 2230 op3(Mulx, rs1, simm13, rd); 2231 } 2232 or(Register rs1, Register rs2, Register rd)2233 public void or(Register rs1, Register rs2, Register rd) { 2234 assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd); 2235 op3(Or, rs1, rs2, rd); 2236 } 2237 or(Register rs1, int simm13, Register rd)2238 public void or(Register rs1, int simm13, Register rd) { 2239 assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd); 2240 op3(Or, rs1, simm13, rd); 2241 } 2242 popc(Register rs2, Register rd)2243 public void popc(Register rs2, Register rd) { 2244 op3(Popc, g0, rs2, rd); 2245 } 2246 popc(int simm13, Register rd)2247 public void popc(int simm13, Register rd) { 2248 op3(Popc, g0, simm13, rd); 2249 } 2250 prefetch(SPARCAddress addr, Fcn fcn)2251 public void prefetch(SPARCAddress addr, Fcn fcn) { 2252 Register rs1 = addr.getBase(); 2253 if (addr.getIndex().equals(Register.None)) { 2254 int dis = addr.getDisplacement(); 2255 assert isSimm13(dis); 2256 fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1)); 2257 } else { 2258 Register rs2 = addr.getIndex(); 2259 fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding); 2260 } 2261 } 2262 2263 // A.44 Read State Register 2264 rdpc(Register rd)2265 public void rdpc(Register rd) { 2266 op3(Rd, g5, g0, rd); 2267 } 2268 restore(Register rs1, Register rs2, Register rd)2269 public void restore(Register rs1, Register rs2, Register rd) { 2270 op3(Restore, rs1, rs2, rd); 2271 } 2272 2273 public static final int PC_RETURN_OFFSET = 8; 2274 save(Register rs1, Register rs2, Register rd)2275 public void save(Register rs1, Register rs2, Register rd) { 2276 op3(Save, rs1, rs2, rd); 2277 } 2278 save(Register rs1, int simm13, Register rd)2279 public void save(Register rs1, int simm13, Register rd) { 2280 op3(Save, rs1, simm13, rd); 2281 } 2282 sdivx(Register rs1, Register rs2, Register rd)2283 public void sdivx(Register rs1, Register rs2, Register rd) { 2284 op3(Sdivx, rs1, rs2, rd); 2285 } 2286 sdivx(Register rs1, int simm13, Register rd)2287 public void sdivx(Register rs1, int simm13, Register rd) { 2288 op3(Sdivx, rs1, simm13, rd); 2289 } 2290 udivx(Register rs1, Register rs2, Register rd)2291 public void udivx(Register rs1, Register rs2, Register rd) { 2292 op3(Udivx, rs1, rs2, rd); 2293 } 2294 udivx(Register rs1, int simm13, Register rd)2295 public void udivx(Register rs1, int simm13, Register rd) { 2296 op3(Udivx, rs1, simm13, rd); 2297 } 2298 sll(Register rs1, Register rs2, Register rd)2299 public void sll(Register rs1, Register rs2, Register rd) { 2300 op3(Sll, rs1, rs2, rd); 2301 } 2302 sll(Register rs1, int shcnt32, Register rd)2303 public void sll(Register rs1, int shcnt32, Register rd) { 2304 assert isImm(shcnt32, 5); 2305 op3(Sll, rs1, shcnt32, rd); 2306 } 2307 sllx(Register rs1, Register rs2, Register rd)2308 public void sllx(Register rs1, Register rs2, Register rd) { 2309 op3(Sllx, rs1, rs2, rd); 2310 } 2311 sllx(Register rs1, int shcnt64, Register rd)2312 public void sllx(Register rs1, int shcnt64, Register rd) { 2313 assert isImm(shcnt64, 6); 2314 op3(Sllx, rs1, shcnt64, rd); 2315 } 2316 sra(Register rs1, Register rs2, Register rd)2317 public void sra(Register rs1, Register rs2, Register rd) { 2318 op3(Sra, rs1, rs2, rd); 2319 } 2320 sra(Register rs1, int simm13, Register rd)2321 public void sra(Register rs1, int simm13, Register rd) { 2322 op3(Sra, rs1, simm13, rd); 2323 } 2324 srax(Register rs1, Register rs2, Register rd)2325 public void srax(Register rs1, Register rs2, Register rd) { 2326 op3(Srax, rs1, rs2, rd); 2327 } 2328 srax(Register rs1, int shcnt64, Register rd)2329 public void srax(Register rs1, int shcnt64, Register rd) { 2330 assert isImm(shcnt64, 6); 2331 op3(Srax, rs1, shcnt64, rd); 2332 } 2333 srl(Register rs1, Register rs2, Register rd)2334 public void srl(Register rs1, Register rs2, Register rd) { 2335 op3(Srl, rs1, rs2, rd); 2336 } 2337 srl(Register rs1, int simm13, Register rd)2338 public void srl(Register rs1, int simm13, Register rd) { 2339 op3(Srl, rs1, simm13, rd); 2340 } 2341 srlx(Register rs1, Register rs2, Register rd)2342 public void srlx(Register rs1, Register rs2, Register rd) { 2343 op3(Srlx, rs1, rs2, rd); 2344 } 2345 srlx(Register rs1, int shcnt64, Register rd)2346 public void srlx(Register rs1, int shcnt64, Register rd) { 2347 assert isImm(shcnt64, 6); 2348 op3(Srlx, rs1, shcnt64, rd); 2349 } 2350 sub(Register rs1, Register rs2, Register rd)2351 public void sub(Register rs1, Register rs2, Register rd) { 2352 op3(Sub, rs1, rs2, rd); 2353 } 2354 sub(Register rs1, int simm13, Register rd)2355 public void sub(Register rs1, int simm13, Register rd) { 2356 op3(Sub, rs1, simm13, rd); 2357 } 2358 subcc(Register rs1, Register rs2, Register rd)2359 public void subcc(Register rs1, Register rs2, Register rd) { 2360 op3(Subcc, rs1, rs2, rd); 2361 } 2362 subcc(Register rs1, int simm13, Register rd)2363 public void subcc(Register rs1, int simm13, Register rd) { 2364 op3(Subcc, rs1, simm13, rd); 2365 } 2366 ta(int trap)2367 public void ta(int trap) { 2368 tcc(Icc, Always, trap); 2369 } 2370 pause()2371 public void pause() { 2372 // Maybe fmt10(rd=0b1_1011, op3=0b11_0000, rs1=0, i=1, simm13=1), or 2373 // maybe op3(Wr, g0, 1, %pause). 2374 // What should the count be? 2375 GraalError.unimplemented("The SPARC pause instruction is not yet implemented."); 2376 } 2377 tcc(CC cc, ConditionFlag flag, int trap)2378 public void tcc(CC cc, ConditionFlag flag, int trap) { 2379 assert isImm(trap, 8); 2380 int b = cc.value << 11; 2381 b |= 1 << 13; 2382 b |= trap; 2383 fmt10(flag.value, Op3s.Tcc.getValue(), 0, b); 2384 } 2385 wrccr(Register rs1, Register rs2)2386 public void wrccr(Register rs1, Register rs2) { 2387 op3(Wr, rs1, rs2, g2); 2388 } 2389 wrccr(Register rs1, int simm13)2390 public void wrccr(Register rs1, int simm13) { 2391 op3(Wr, rs1, simm13, g2); 2392 } 2393 xor(Register rs1, Register rs2, Register rd)2394 public void xor(Register rs1, Register rs2, Register rd) { 2395 op3(Xor, rs1, rs2, rd); 2396 } 2397 xor(Register rs1, int simm13, Register rd)2398 public void xor(Register rs1, int simm13, Register rd) { 2399 op3(Xor, rs1, simm13, rd); 2400 } 2401 xorcc(Register rs1, Register rs2, Register rd)2402 public void xorcc(Register rs1, Register rs2, Register rd) { 2403 op3(Xorcc, rs1, rs2, rd); 2404 } 2405 xorcc(Register rs1, int simm13, Register rd)2406 public void xorcc(Register rs1, int simm13, Register rd) { 2407 op3(Xorcc, rs1, simm13, rd); 2408 } 2409 xnor(Register rs1, Register rs2, Register rd)2410 public void xnor(Register rs1, Register rs2, Register rd) { 2411 op3(Xnor, rs1, rs2, rd); 2412 } 2413 xnor(Register rs1, int simm13, Register rd)2414 public void xnor(Register rs1, int simm13, Register rd) { 2415 op3(Xnor, rs1, simm13, rd); 2416 } 2417 2418 /* 2419 * Load/Store 2420 */ ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi)2421 protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) { 2422 Register rs1 = addr.getBase(); 2423 if (!addr.getIndex().equals(Register.None)) { 2424 Register rs2 = addr.getIndex(); 2425 if (asi != null) { 2426 int b = rs2.encoding; 2427 b |= asi.value << 5; 2428 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b); 2429 } else { 2430 op3(op3, rs1, rs2, rd); 2431 } 2432 } else { 2433 int imm = addr.getDisplacement(); 2434 op3(op3, rs1, imm, rd); 2435 } 2436 } 2437 ld(Op3s op3, SPARCAddress addr, Register rd)2438 protected void ld(Op3s op3, SPARCAddress addr, Register rd) { 2439 ld(op3, addr, rd, null); 2440 } 2441 lddf(SPARCAddress src, Register dst)2442 public void lddf(SPARCAddress src, Register dst) { 2443 assert isDoubleFloatRegister(dst) : dst; 2444 ld(Lddf, src, dst); 2445 } 2446 ldf(SPARCAddress src, Register dst)2447 public void ldf(SPARCAddress src, Register dst) { 2448 assert isSingleFloatRegister(dst) : dst; 2449 ld(Ldf, src, dst); 2450 } 2451 lduh(SPARCAddress src, Register dst)2452 public void lduh(SPARCAddress src, Register dst) { 2453 assert isCPURegister(dst) : dst; 2454 ld(Lduh, src, dst); 2455 } 2456 ldsh(SPARCAddress src, Register dst)2457 public void ldsh(SPARCAddress src, Register dst) { 2458 assert isCPURegister(dst) : dst; 2459 ld(Ldsh, src, dst); 2460 } 2461 ld(SPARCAddress src, Register dst, int bytes, boolean signExtend)2462 public void ld(SPARCAddress src, Register dst, int bytes, boolean signExtend) { 2463 if (isCPURegister(dst)) { 2464 if (signExtend) { 2465 switch (bytes) { 2466 case 1: 2467 ld(Ldsb, src, dst); 2468 break; 2469 case 2: 2470 ld(Ldsh, src, dst); 2471 break; 2472 case 4: 2473 ld(Ldsw, src, dst); 2474 break; 2475 case 8: 2476 ld(Ldx, src, dst); 2477 break; 2478 default: 2479 throw new InternalError(); 2480 } 2481 } else { 2482 switch (bytes) { 2483 case 1: 2484 ld(Ldub, src, dst); 2485 break; 2486 case 2: 2487 ld(Lduh, src, dst); 2488 break; 2489 case 4: 2490 ld(Lduw, src, dst); 2491 break; 2492 case 8: 2493 ld(Ldx, src, dst); 2494 break; 2495 default: 2496 throw new InternalError(); 2497 } 2498 } 2499 } else if (isDoubleFloatRegister(dst) && bytes == 8) { 2500 assert !signExtend; 2501 ld(Lddf, src, dst); 2502 } else if (isSingleFloatRegister(dst) && bytes == 4) { 2503 assert !signExtend; 2504 ld(Ldf, src, dst); 2505 } else { 2506 throw new InternalError(String.format("src: %s dst: %s bytes: %d signExtend: %b", src, dst, bytes, signExtend)); 2507 } 2508 } 2509 st(Register src, SPARCAddress dst, int bytes)2510 public void st(Register src, SPARCAddress dst, int bytes) { 2511 if (isCPURegister(src)) { 2512 switch (bytes) { 2513 case 1: 2514 st(Stb, src, dst); 2515 break; 2516 case 2: 2517 st(Sth, src, dst); 2518 break; 2519 case 4: 2520 st(Stw, src, dst); 2521 break; 2522 case 8: 2523 st(Stx, src, dst); 2524 break; 2525 default: 2526 throw new InternalError(Integer.toString(bytes)); 2527 } 2528 } else if (isDoubleFloatRegister(src) && bytes == 8) { 2529 st(Stdf, src, dst); 2530 } else if (isSingleFloatRegister(src) && bytes == 4) { 2531 st(Stf, src, dst); 2532 } else { 2533 throw new InternalError(String.format("src: %s dst: %s bytes: %d", src, dst, bytes)); 2534 } 2535 } 2536 ldub(SPARCAddress src, Register dst)2537 public void ldub(SPARCAddress src, Register dst) { 2538 assert isCPURegister(dst) : dst; 2539 ld(Ldub, src, dst); 2540 } 2541 ldsb(SPARCAddress src, Register dst)2542 public void ldsb(SPARCAddress src, Register dst) { 2543 assert isCPURegister(dst) : dst; 2544 ld(Ldsb, src, dst); 2545 } 2546 lduw(SPARCAddress src, Register dst)2547 public void lduw(SPARCAddress src, Register dst) { 2548 assert isCPURegister(dst) : dst; 2549 ld(Lduw, src, dst); 2550 } 2551 ldsw(SPARCAddress src, Register dst)2552 public void ldsw(SPARCAddress src, Register dst) { 2553 assert isCPURegister(dst) : dst; 2554 ld(Ldsw, src, dst); 2555 } 2556 ldx(SPARCAddress src, Register dst)2557 public void ldx(SPARCAddress src, Register dst) { 2558 assert isCPURegister(dst) : dst; 2559 ld(Ldx, src, dst); 2560 } 2561 ldxa(Register rs1, Register rs2, Register rd, Asi asi)2562 public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) { 2563 assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); 2564 ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi); 2565 } 2566 lduwa(Register rs1, Register rs2, Register rd, Asi asi)2567 public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) { 2568 assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); 2569 ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi); 2570 } 2571 stxa(Register rd, Register rs1, Register rs2, Asi asi)2572 public void stxa(Register rd, Register rs1, Register rs2, Asi asi) { 2573 assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); 2574 ld(Stxa, new SPARCAddress(rs1, rs2), rd, asi); 2575 } 2576 st(Op3s op3, Register rs1, SPARCAddress dest)2577 protected void st(Op3s op3, Register rs1, SPARCAddress dest) { 2578 ld(op3, dest, rs1); 2579 } 2580 stdf(Register rd, SPARCAddress addr)2581 public void stdf(Register rd, SPARCAddress addr) { 2582 assert isDoubleFloatRegister(rd) : rd; 2583 st(Stdf, rd, addr); 2584 } 2585 stf(Register rd, SPARCAddress addr)2586 public void stf(Register rd, SPARCAddress addr) { 2587 assert isSingleFloatRegister(rd) : rd; 2588 st(Stf, rd, addr); 2589 } 2590 stb(Register rd, SPARCAddress addr)2591 public void stb(Register rd, SPARCAddress addr) { 2592 assert isCPURegister(rd) : rd; 2593 st(Stb, rd, addr); 2594 } 2595 sth(Register rd, SPARCAddress addr)2596 public void sth(Register rd, SPARCAddress addr) { 2597 assert isCPURegister(rd) : rd; 2598 st(Sth, rd, addr); 2599 } 2600 stw(Register rd, SPARCAddress addr)2601 public void stw(Register rd, SPARCAddress addr) { 2602 assert isCPURegister(rd) : rd; 2603 st(Stw, rd, addr); 2604 } 2605 stx(Register rd, SPARCAddress addr)2606 public void stx(Register rd, SPARCAddress addr) { 2607 assert isCPURegister(rd) : rd; 2608 st(Stx, rd, addr); 2609 } 2610 membar(int barriers)2611 public void membar(int barriers) { 2612 op3(Membar, o7, barriers, g0); 2613 } 2614 casa(Register rs1, Register rs2, Register rd, Asi asi)2615 public void casa(Register rs1, Register rs2, Register rd, Asi asi) { 2616 ld(Casa, new SPARCAddress(rs1, rs2), rd, asi); 2617 } 2618 casxa(Register rs1, Register rs2, Register rd, Asi asi)2619 public void casxa(Register rs1, Register rs2, Register rd, Asi asi) { 2620 ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi); 2621 } 2622 2623 @Override getInstructionCounter()2624 public InstructionCounter getInstructionCounter() { 2625 return new SPARCInstructionCounter(this); 2626 } 2627 patchAddImmediate(int position, int simm13)2628 public void patchAddImmediate(int position, int simm13) { 2629 int inst = getInt(position); 2630 assert SPARCAssembler.isSimm13(simm13) : simm13; 2631 assert (inst >>> 30) == 0b10 : String.format("0x%x", inst); 2632 assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst); 2633 assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst); 2634 inst = inst & (~((1 << 13) - 1)); 2635 inst |= simm13 & ((1 << 12) - 1); 2636 emitInt(inst, position); 2637 } 2638 fpadd32(Register rs1, Register rs2, Register rd)2639 public void fpadd32(Register rs1, Register rs2, Register rd) { 2640 op3(Impdep1, Fpadd32, rs1, rs2, rd); 2641 } 2642 2643 /** 2644 * Does peephole optimization on code generated by this assembler. This method should be called 2645 * at the end of code generation. 2646 * <p> 2647 * It searches for conditional branch instructions which has nop in the delay slot then looks at 2648 * the instruction at branch target; if it is an arithmetic instruction, which does not throw an 2649 * exception (e.g. division), it pulls this instruction into the delay slot and increments the 2650 * displacement by 1. 2651 */ peephole()2652 public void peephole() { 2653 for (int i : delaySlotOptimizationPoints) { 2654 optimizeDelaySlot(i); 2655 } 2656 } 2657 2658 /** 2659 * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff 2660 * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul 2661 * flag and increments <i>b</i>s disp field by 1; 2662 * <p> 2663 * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to 2664 * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp 2665 * field to <i>b</i>s disp field. 2666 */ optimizeDelaySlot(int i)2667 private void optimizeDelaySlot(int i) { 2668 int delaySlotAbsolute = i + INSTRUCTION_SIZE; 2669 int nextInst = getInt(delaySlotAbsolute); 2670 SPARCOp nextOp = getSPARCOp(nextInst); 2671 if (nextOp instanceof Sethi && Sethi.isNop(nextInst)) { 2672 int inst = getInt(i); 2673 SPARCOp op = getSPARCOp(inst); 2674 if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) { 2675 ControlTransferOp ctOp = (ControlTransferOp) op; 2676 int disp = ctOp.getDisp(inst); 2677 int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE; 2678 int branchTargetInst = getInt(branchTargetAbsolute); 2679 SPARCOp branchTargetOp = getSPARCOp(branchTargetInst); 2680 if (branchTargetOp instanceof Op3Op) { 2681 Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst); 2682 if (!op3.throwsException()) { 2683 inst = ctOp.setDisp(inst, disp + 1); // Increment the offset 2684 inst = ctOp.setAnnul(inst, true); 2685 emitInt(inst, i); 2686 emitInt(branchTargetInst, delaySlotAbsolute); 2687 } 2688 } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) { 2689 // If branchtarget is a unconditional branch 2690 ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp; 2691 int btDisp = branchTargetOpBranch.getDisp(branchTargetInst); 2692 int newDisp = disp + btDisp; 2693 if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size 2694 int instAfter = ctOp.setDisp(inst, newDisp); 2695 instAfter = ctOp.setAnnul(instAfter, true); 2696 branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE); 2697 branchTargetOp = getSPARCOp(branchTargetInst); 2698 if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) { 2699 emitInt(instAfter, i); 2700 emitInt(branchTargetInst, delaySlotAbsolute); 2701 } 2702 } 2703 } 2704 } 2705 } 2706 } 2707 } 2708