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