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