001/* 002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.sparc; 024 025import static com.oracle.graal.asm.sparc.SPARCAssembler.*; 026import static com.oracle.graal.asm.sparc.SPARCAssembler.Annul.*; 027import static com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict.*; 028import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.*; 029import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.*; 030import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.*; 031import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 032import static jdk.internal.jvmci.code.ValueUtil.*; 033import static jdk.internal.jvmci.sparc.SPARC.*; 034import jdk.internal.jvmci.code.*; 035import jdk.internal.jvmci.common.*; 036import jdk.internal.jvmci.meta.*; 037import jdk.internal.jvmci.sparc.*; 038 039import com.oracle.graal.asm.*; 040import com.oracle.graal.asm.sparc.*; 041import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister; 042import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; 043import com.oracle.graal.lir.*; 044import com.oracle.graal.lir.asm.*; 045import com.oracle.graal.lir.gen.*; 046 047public enum SPARCArithmetic { 048 // @formatter:off 049 IADD, ISUB, IMUL, IUMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, 050 LADD, LSUB, LMUL, LUMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, 051 IADDCC, ISUBCC, IMULCC, 052 LADDCC, LSUBCC, LMULCC, 053 FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, 054 DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, 055 INEG, LNEG, FNEG, DNEG, INOT, LNOT, 056 L2I, B2I, S2I, B2L, S2L, I2L, 057 F2D, D2F, 058 I2F, I2D, F2I, D2I, 059 L2F, L2D, F2L, D2L; 060 // @formatter:on 061 062 /** 063 * Unary operation with separate source and destination operand. 064 */ 065 public static final class Unary2Op extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { 066 public static final LIRInstructionClass<Unary2Op> TYPE = LIRInstructionClass.create(Unary2Op.class); 067 public static final SizeEstimate SIZE_1 = SizeEstimate.create(1); 068 public static final SizeEstimate SIZE_5 = SizeEstimate.create(5); 069 070 @Opcode private final SPARCArithmetic opcode; 071 @Def({REG, HINT}) protected AllocatableValue result; 072 @Use({REG}) protected AllocatableValue x; 073 074 public Unary2Op(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x) { 075 super(TYPE); 076 this.opcode = opcode; 077 this.result = result; 078 this.x = x; 079 } 080 081 @Override 082 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 083 emitUnary(crb, masm, opcode, result, x, null, delayedControlTransfer); 084 } 085 086 @Override 087 public SizeEstimate estimateSize() { 088 switch (opcode) { 089 case F2L: 090 case F2I: 091 case D2L: 092 case D2I: 093 return SIZE_5; 094 default: 095 return SIZE_1; 096 } 097 } 098 } 099 100 /** 101 * Binary operation with two operands. The first source operand is combined with the 102 * destination. The second source operand must be a register. 103 */ 104 public static final class BinaryRegReg extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { 105 public static final LIRInstructionClass<BinaryRegReg> TYPE = LIRInstructionClass.create(BinaryRegReg.class); 106 public static final SizeEstimate SIZE_1 = SizeEstimate.create(1); 107 public static final SizeEstimate SIZE_3 = SizeEstimate.create(3); 108 public static final SizeEstimate SIZE_7 = SizeEstimate.create(7); 109 110 @Opcode private final SPARCArithmetic opcode; 111 @Def({REG}) protected Value result; 112 @Use({REG}) protected Value x; 113 @Alive({REG}) protected Value y; 114 @State LIRFrameState state; 115 116 public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y) { 117 this(opcode, result, x, y, null); 118 } 119 120 public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { 121 super(TYPE); 122 this.opcode = opcode; 123 this.result = result; 124 this.x = x; 125 this.y = y; 126 this.state = state; 127 } 128 129 @Override 130 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 131 emitRegReg(crb, masm, opcode, result, x, y, state, delayedControlTransfer); 132 } 133 134 @Override 135 public void verify() { 136 super.verify(); 137 verifyKind(opcode, result, x, y); 138 } 139 140 @Override 141 public SizeEstimate estimateSize() { 142 switch (opcode) { 143 case IMULCC: 144 return SIZE_7; 145 case IUDIV: 146 case IDIV: 147 return SIZE_3; 148 default: 149 return SIZE_1; 150 } 151 } 152 } 153 154 /** 155 * Binary operation with single source/destination operand and one constant. 156 */ 157 public static final class BinaryRegConst extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { 158 public static final LIRInstructionClass<BinaryRegConst> TYPE = LIRInstructionClass.create(BinaryRegConst.class); 159 public static final SizeEstimate SIZE = SizeEstimate.create(1); 160 161 @Opcode private final SPARCArithmetic opcode; 162 @Def({REG}) protected AllocatableValue result; 163 @Use({REG}) protected Value x; 164 @State protected LIRFrameState state; 165 protected JavaConstant y; 166 167 public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, Value x, JavaConstant y) { 168 this(opcode, result, x, y, null); 169 } 170 171 public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, Value x, JavaConstant y, LIRFrameState state) { 172 super(TYPE, SIZE); 173 this.opcode = opcode; 174 this.result = result; 175 this.x = x; 176 this.y = y; 177 this.state = state; 178 } 179 180 @Override 181 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 182 emitRegConstant(crb, masm, opcode, result, x, y, null, delayedControlTransfer); 183 } 184 185 @Override 186 public void verify() { 187 super.verify(); 188 verifyKind(opcode, result, x, y); 189 } 190 } 191 192 /** 193 * Special LIR instruction as it requires a bunch of scratch registers. 194 */ 195 public static final class RemOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { 196 public static final LIRInstructionClass<RemOp> TYPE = LIRInstructionClass.create(RemOp.class); 197 public static final SizeEstimate SIZE = SizeEstimate.create(4); 198 199 @Opcode private final SPARCArithmetic opcode; 200 @Def({REG}) protected Value result; 201 @Alive({REG, CONST}) protected Value x; 202 @Alive({REG, CONST}) protected Value y; 203 @Temp({REG}) protected Value scratch1; 204 @Temp({REG}) protected Value scratch2; 205 @State protected LIRFrameState state; 206 207 public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) { 208 super(TYPE, SIZE); 209 this.opcode = opcode; 210 this.result = result; 211 this.x = x; 212 this.y = y; 213 this.scratch1 = gen.newVariable(LIRKind.combine(x, y)); 214 this.scratch2 = gen.newVariable(LIRKind.combine(x, y)); 215 this.state = state; 216 } 217 218 @Override 219 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 220 emitRem(crb, masm, opcode, result, x, y, scratch1, scratch2, state, delayedControlTransfer); 221 } 222 223 @Override 224 public void verify() { 225 super.verify(); 226 verifyKind(opcode, result, x, y); 227 } 228 } 229 230 /** 231 * Calculates the product and condition code for long multiplication of long values. 232 */ 233 public static final class SPARCLMulccOp extends SPARCLIRInstruction { 234 public static final LIRInstructionClass<SPARCLMulccOp> TYPE = LIRInstructionClass.create(SPARCLMulccOp.class); 235 public static final SizeEstimate SIZE = SizeEstimate.create(13); 236 237 @Def({REG}) protected Value result; 238 @Alive({REG}) protected Value x; 239 @Alive({REG}) protected Value y; 240 @Temp({REG}) protected Value scratch1; 241 @Temp({REG}) protected Value scratch2; 242 243 public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) { 244 super(TYPE, SIZE); 245 this.result = result; 246 this.x = x; 247 this.y = y; 248 this.scratch1 = gen.newVariable(LIRKind.combine(x, y)); 249 this.scratch2 = gen.newVariable(LIRKind.combine(x, y)); 250 } 251 252 @Override 253 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 254 Label noOverflow = new Label(); 255 masm.mulx(asLongReg(x), asLongReg(y), asLongReg(result)); 256 257 // Calculate the upper 64 bit signed := (umulxhi product - (x{63}&y + y{63}&x)) 258 masm.umulxhi(asLongReg(x), asLongReg(y), asLongReg(scratch1)); 259 masm.srax(asLongReg(x), 63, asLongReg(scratch2)); 260 masm.and(asLongReg(scratch2), asLongReg(y), asLongReg(scratch2)); 261 masm.sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)); 262 263 masm.srax(asLongReg(y), 63, asLongReg(scratch2)); 264 masm.and(asLongReg(scratch2), asLongReg(x), asLongReg(scratch2)); 265 masm.sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)); 266 267 // Now construct the lower half and compare 268 masm.srax(asLongReg(result), 63, asLongReg(scratch2)); 269 masm.cmp(asLongReg(scratch1), asLongReg(scratch2)); 270 masm.bpcc(Equal, NOT_ANNUL, noOverflow, Xcc, PREDICT_TAKEN); 271 masm.nop(); 272 masm.wrccr(g0, 1 << (CCR_XCC_SHIFT + CCR_V_SHIFT)); 273 masm.bind(noOverflow); 274 } 275 } 276 277 private static void emitRegConstant(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, JavaConstant src2, LIRFrameState info, 278 SPARCDelayedControlTransfer delaySlotLir) { 279 assert isSimm13(crb.asIntConst(src2)) : src2; 280 int constant = crb.asIntConst(src2); 281 int exceptionOffset = -1; 282 delaySlotLir.emitControlTransfer(crb, masm); 283 switch (opcode) { 284 case IADD: 285 masm.add(asIntReg(src1), constant, asIntReg(dst)); 286 break; 287 case IADDCC: 288 masm.addcc(asIntReg(src1), constant, asIntReg(dst)); 289 break; 290 case ISUB: 291 masm.sub(asIntReg(src1), constant, asIntReg(dst)); 292 break; 293 case ISUBCC: 294 masm.subcc(asIntReg(src1), constant, asIntReg(dst)); 295 break; 296 case IMUL: 297 masm.mulx(asIntReg(src1), constant, asIntReg(dst)); 298 break; 299 case IMULCC: 300 throw JVMCIError.unimplemented(); 301 case IDIV: 302 masm.sra(asRegister(src1), 0, asRegister(src1)); 303 masm.sdivx(asIntReg(src1), constant, asIntReg(dst)); 304 break; 305 case IUDIV: 306 masm.srl(asRegister(src1), 0, asRegister(src1)); 307 masm.udivx(asIntReg(src1), constant, asIntReg(dst)); 308 break; 309 case IAND: 310 masm.and(asIntReg(src1), constant, asIntReg(dst)); 311 break; 312 case ISHL: 313 masm.sll(asIntReg(src1), constant, asIntReg(dst)); 314 break; 315 case ISHR: 316 masm.sra(asIntReg(src1), constant, asIntReg(dst)); 317 break; 318 case IUSHR: 319 masm.srl(asIntReg(src1), constant, asIntReg(dst)); 320 break; 321 case IOR: 322 masm.or(asIntReg(src1), constant, asIntReg(dst)); 323 break; 324 case IXOR: 325 masm.xor(asIntReg(src1), constant, asIntReg(dst)); 326 break; 327 case LADD: 328 masm.add(asLongReg(src1), constant, asLongReg(dst)); 329 break; 330 case LADDCC: 331 masm.addcc(asLongReg(src1), constant, asLongReg(dst)); 332 break; 333 case LSUB: 334 masm.sub(asLongReg(src1), constant, asLongReg(dst)); 335 break; 336 case LSUBCC: 337 masm.subcc(asLongReg(src1), constant, asLongReg(dst)); 338 break; 339 case LMUL: 340 masm.mulx(asLongReg(src1), constant, asLongReg(dst)); 341 break; 342 case LDIV: 343 exceptionOffset = masm.position(); 344 masm.sdivx(asLongReg(src1), constant, asLongReg(dst)); 345 break; 346 case LUDIV: 347 exceptionOffset = masm.position(); 348 masm.udivx(asLongReg(src1), constant, asLongReg(dst)); 349 break; 350 case LAND: 351 masm.and(asLongReg(src1), constant, asLongReg(dst)); 352 break; 353 case LOR: 354 masm.or(asLongReg(src1), constant, asLongReg(dst)); 355 break; 356 case LXOR: 357 masm.xor(asLongReg(src1), constant, asLongReg(dst)); 358 break; 359 case LSHL: 360 masm.sllx(asLongReg(src1), constant, asLongReg(dst)); 361 break; 362 case LSHR: 363 masm.srax(asLongReg(src1), constant, asLongReg(dst)); 364 break; 365 case LUSHR: 366 masm.srlx(asLongReg(src1), constant, asLongReg(dst)); 367 break; 368 case DAND: // Has no constant implementation in SPARC 369 case FADD: 370 case FMUL: 371 case FDIV: 372 case DADD: 373 case DMUL: 374 case DDIV: 375 default: 376 throw JVMCIError.shouldNotReachHere(); 377 } 378 if (info != null) { 379 assert exceptionOffset != -1; 380 crb.recordImplicitException(exceptionOffset, info); 381 } 382 } 383 384 public static void emitRegReg(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info, 385 SPARCDelayedControlTransfer delaySlotLir) { 386 int exceptionOffset = -1; 387 assert !isConstant(src1) : src1; 388 assert !isConstant(src2) : src2; 389 switch (opcode) { 390 case IADD: 391 delaySlotLir.emitControlTransfer(crb, masm); 392 masm.add(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 393 break; 394 case IADDCC: 395 delaySlotLir.emitControlTransfer(crb, masm); 396 masm.addcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 397 break; 398 case ISUB: 399 delaySlotLir.emitControlTransfer(crb, masm); 400 masm.sub(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 401 break; 402 case ISUBCC: 403 delaySlotLir.emitControlTransfer(crb, masm); 404 masm.subcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 405 break; 406 case IMUL: 407 delaySlotLir.emitControlTransfer(crb, masm); 408 masm.mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 409 break; 410 case IMULCC: 411 try (ScratchRegister tmpScratch = masm.getScratchRegister()) { 412 Register tmp = tmpScratch.getRegister(); 413 masm.mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 414 Label noOverflow = new Label(); 415 masm.sra(asIntReg(dst), 0, tmp); 416 masm.xorcc(SPARC.g0, SPARC.g0, SPARC.g0); 417 if (masm.hasFeature(SPARC.CPUFeature.CBCOND)) { 418 masm.cbcondx(Equal, tmp, asIntReg(dst), noOverflow); 419 // Is necessary, otherwise we will have a penalty of 5 cycles in S3 420 masm.nop(); 421 } else { 422 masm.cmp(tmp, asIntReg(dst)); 423 masm.bpcc(Equal, NOT_ANNUL, noOverflow, Xcc, PREDICT_TAKEN); 424 masm.nop(); 425 } 426 masm.wrccr(SPARC.g0, 1 << (SPARCAssembler.CCR_ICC_SHIFT + SPARCAssembler.CCR_V_SHIFT)); 427 masm.bind(noOverflow); 428 } 429 break; 430 case IDIV: 431 masm.signx(asIntReg(src1), asIntReg(src1)); 432 masm.signx(asIntReg(src2), asIntReg(src2)); 433 delaySlotLir.emitControlTransfer(crb, masm); 434 exceptionOffset = masm.position(); 435 masm.sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 436 break; 437 case IUDIV: 438 masm.srl(asIntReg(src1), 0, asIntReg(src1)); 439 masm.srl(asIntReg(src2), 0, asIntReg(src2)); 440 delaySlotLir.emitControlTransfer(crb, masm); 441 exceptionOffset = masm.position(); 442 masm.udivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 443 break; 444 case IAND: 445 delaySlotLir.emitControlTransfer(crb, masm); 446 masm.and(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 447 break; 448 case IOR: 449 delaySlotLir.emitControlTransfer(crb, masm); 450 masm.or(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 451 break; 452 case IXOR: 453 delaySlotLir.emitControlTransfer(crb, masm); 454 masm.xor(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 455 break; 456 case ISHL: 457 delaySlotLir.emitControlTransfer(crb, masm); 458 masm.sll(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 459 break; 460 case ISHR: 461 delaySlotLir.emitControlTransfer(crb, masm); 462 masm.sra(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 463 break; 464 case IUSHR: 465 delaySlotLir.emitControlTransfer(crb, masm); 466 masm.srl(asIntReg(src1), asIntReg(src2), asIntReg(dst)); 467 break; 468 case IREM: 469 throw JVMCIError.unimplemented(); 470 case LADD: 471 delaySlotLir.emitControlTransfer(crb, masm); 472 masm.add(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 473 break; 474 case LADDCC: 475 delaySlotLir.emitControlTransfer(crb, masm); 476 masm.addcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 477 break; 478 case LSUB: 479 delaySlotLir.emitControlTransfer(crb, masm); 480 masm.sub(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 481 break; 482 case LSUBCC: 483 delaySlotLir.emitControlTransfer(crb, masm); 484 masm.subcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 485 break; 486 case LMUL: 487 delaySlotLir.emitControlTransfer(crb, masm); 488 masm.mulx(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 489 break; 490 case LMULCC: 491 throw JVMCIError.unimplemented(); 492 case LDIV: 493 delaySlotLir.emitControlTransfer(crb, masm); 494 exceptionOffset = masm.position(); 495 masm.sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 496 break; 497 case LUDIV: 498 delaySlotLir.emitControlTransfer(crb, masm); 499 exceptionOffset = masm.position(); 500 masm.udivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 501 break; 502 case LAND: 503 delaySlotLir.emitControlTransfer(crb, masm); 504 masm.and(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 505 break; 506 case LOR: 507 delaySlotLir.emitControlTransfer(crb, masm); 508 masm.or(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 509 break; 510 case LXOR: 511 delaySlotLir.emitControlTransfer(crb, masm); 512 masm.xor(asLongReg(src1), asLongReg(src2), asLongReg(dst)); 513 break; 514 case LSHL: 515 delaySlotLir.emitControlTransfer(crb, masm); 516 masm.sllx(asLongReg(src1), asIntReg(src2), asLongReg(dst)); 517 break; 518 case LSHR: 519 delaySlotLir.emitControlTransfer(crb, masm); 520 masm.srax(asLongReg(src1), asIntReg(src2), asLongReg(dst)); 521 break; 522 case LUSHR: 523 delaySlotLir.emitControlTransfer(crb, masm); 524 masm.srlx(asLongReg(src1), asIntReg(src2), asLongReg(dst)); 525 break; 526 case FADD: 527 delaySlotLir.emitControlTransfer(crb, masm); 528 masm.fadds(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)); 529 break; 530 case FSUB: 531 delaySlotLir.emitControlTransfer(crb, masm); 532 masm.fsubs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)); 533 break; 534 case FMUL: 535 delaySlotLir.emitControlTransfer(crb, masm); 536 if (dst.getPlatformKind() == Kind.Double) { 537 masm.fsmuld(asFloatReg(src1), asFloatReg(src2), asDoubleReg(dst)); 538 } else if (dst.getPlatformKind() == Kind.Float) { 539 masm.fmuls(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)); 540 } 541 break; 542 case FDIV: 543 delaySlotLir.emitControlTransfer(crb, masm); 544 exceptionOffset = masm.position(); 545 masm.fdivs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)); 546 break; 547 case FREM: 548 throw JVMCIError.unimplemented(); 549 case DADD: 550 delaySlotLir.emitControlTransfer(crb, masm); 551 masm.faddd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)); 552 break; 553 case DSUB: 554 delaySlotLir.emitControlTransfer(crb, masm); 555 masm.fsubd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)); 556 break; 557 case DMUL: 558 delaySlotLir.emitControlTransfer(crb, masm); 559 masm.fmuld(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)); 560 break; 561 case DDIV: 562 delaySlotLir.emitControlTransfer(crb, masm); 563 exceptionOffset = masm.position(); 564 masm.fdivd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)); 565 break; 566 case DREM: 567 throw JVMCIError.unimplemented(); 568 case DAND: 569 delaySlotLir.emitControlTransfer(crb, masm); 570 masm.fandd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)); 571 break; 572 default: 573 throw JVMCIError.shouldNotReachHere(); 574 } 575 if (info != null) { 576 assert exceptionOffset != -1; 577 crb.recordImplicitException(exceptionOffset, info); 578 } 579 } 580 581 public static void emitRem(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info, 582 SPARCDelayedControlTransfer delaySlotLir) { 583 int exceptionOffset = -1; 584 if (!isConstant(src1) && isConstant(src2)) { 585 assert isSimm13(crb.asIntConst(src2)); 586 assert !src1.equals(scratch1); 587 assert !src1.equals(scratch2); 588 assert !src2.equals(scratch1); 589 switch (opcode) { 590 case IREM: 591 masm.sra(asIntReg(src1), 0, asIntReg(dst)); 592 exceptionOffset = masm.position(); 593 masm.sdivx(asIntReg(dst), crb.asIntConst(src2), asIntReg(scratch1)); 594 masm.mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)); 595 delaySlotLir.emitControlTransfer(crb, masm); 596 masm.sub(asIntReg(dst), asIntReg(scratch2), asIntReg(dst)); 597 break; 598 case LREM: 599 exceptionOffset = masm.position(); 600 masm.sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)); 601 masm.mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)); 602 delaySlotLir.emitControlTransfer(crb, masm); 603 masm.sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)); 604 break; 605 case LUREM: 606 exceptionOffset = masm.position(); 607 masm.udivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)); 608 masm.mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)); 609 delaySlotLir.emitControlTransfer(crb, masm); 610 masm.sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)); 611 break; 612 case IUREM: 613 JVMCIError.unimplemented(); 614 break; 615 default: 616 throw JVMCIError.shouldNotReachHere(); 617 } 618 } else if (isRegister(src1) && isRegister(src2)) { 619 Value srcLeft = src1; 620 switch (opcode) { 621 case LREM: 622 if (isConstant(src1)) { 623 new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm); 624 srcLeft = scratch2; 625 } 626 assert !asLongReg(srcLeft).equals(asLongReg(scratch1)); 627 assert !asLongReg(src2).equals(asLongReg(scratch1)); 628 // But src2 can be scratch2 629 exceptionOffset = masm.position(); 630 masm.sdivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)); 631 masm.mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)); 632 delaySlotLir.emitControlTransfer(crb, masm); 633 masm.sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)); 634 break; 635 case LUREM: 636 if (isConstant(src1)) { 637 new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm); 638 srcLeft = scratch2; 639 } 640 assert !asLongReg(srcLeft).equals(asLongReg(scratch1)); 641 assert !asLongReg(src2).equals(asLongReg(scratch1)); 642 exceptionOffset = masm.position(); 643 masm.udivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)); 644 masm.mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)); 645 delaySlotLir.emitControlTransfer(crb, masm); 646 masm.sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)); 647 break; 648 case IREM: 649 if (isConstant(src1)) { 650 new Setx(crb.asIntConst(src1), asIntReg(scratch2), false).emit(masm); 651 srcLeft = scratch2; 652 } 653 assert !asIntReg(srcLeft).equals(asIntReg(scratch1)); 654 assert !asIntReg(src2).equals(asIntReg(scratch1)); 655 masm.sra(asIntReg(src1), 0, asIntReg(scratch1)); 656 masm.sra(asIntReg(src2), 0, asIntReg(scratch2)); 657 exceptionOffset = masm.position(); 658 masm.sdivx(asIntReg(scratch1), asIntReg(scratch2), asIntReg(dst)); 659 masm.mulx(asIntReg(dst), asIntReg(scratch2), asIntReg(dst)); 660 delaySlotLir.emitControlTransfer(crb, masm); 661 masm.sub(asIntReg(scratch1), asIntReg(dst), asIntReg(dst)); 662 break; 663 case IUREM: 664 assert !asIntReg(dst).equals(asIntReg(scratch1)); 665 assert !asIntReg(dst).equals(asIntReg(scratch2)); 666 masm.srl(asIntReg(src1), 0, asIntReg(scratch1)); 667 masm.srl(asIntReg(src2), 0, asIntReg(dst)); 668 exceptionOffset = masm.position(); 669 masm.udivx(asIntReg(scratch1), asIntReg(dst), asIntReg(scratch2)); 670 masm.mulx(asIntReg(scratch2), asIntReg(dst), asIntReg(dst)); 671 delaySlotLir.emitControlTransfer(crb, masm); 672 masm.sub(asIntReg(scratch1), asIntReg(dst), asIntReg(dst)); 673 break; 674 default: 675 throw JVMCIError.shouldNotReachHere(); 676 } 677 } else { 678 throw JVMCIError.shouldNotReachHere(); 679 } 680 if (info != null) { 681 assert exceptionOffset != -1; 682 crb.recordImplicitException(exceptionOffset, info); 683 } 684 } 685 686 public static void emitUnary(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info, SPARCDelayedControlTransfer delaySlotLir) { 687 int exceptionOffset = -1; 688 Label notOrdered = new Label(); 689 switch (opcode) { 690 case INEG: 691 delaySlotLir.emitControlTransfer(crb, masm); 692 masm.neg(asIntReg(src), asIntReg(dst)); 693 break; 694 case LNEG: 695 delaySlotLir.emitControlTransfer(crb, masm); 696 masm.neg(asLongReg(src), asLongReg(dst)); 697 break; 698 case INOT: 699 delaySlotLir.emitControlTransfer(crb, masm); 700 masm.not(asIntReg(src), asIntReg(dst)); 701 break; 702 case LNOT: 703 delaySlotLir.emitControlTransfer(crb, masm); 704 masm.not(asLongReg(src), asLongReg(dst)); 705 break; 706 case D2F: 707 delaySlotLir.emitControlTransfer(crb, masm); 708 masm.fdtos(asDoubleReg(src), asFloatReg(dst)); 709 break; 710 case L2D: 711 delaySlotLir.emitControlTransfer(crb, masm); 712 masm.fxtod(asDoubleReg(src), asDoubleReg(dst)); 713 break; 714 case L2F: 715 delaySlotLir.emitControlTransfer(crb, masm); 716 masm.fxtos(asDoubleReg(src), asFloatReg(dst)); 717 break; 718 case I2D: 719 delaySlotLir.emitControlTransfer(crb, masm); 720 masm.fitod(asFloatReg(src), asDoubleReg(dst)); 721 break; 722 case I2L: 723 delaySlotLir.emitControlTransfer(crb, masm); 724 masm.signx(asIntReg(src), asLongReg(dst)); 725 break; 726 case L2I: 727 delaySlotLir.emitControlTransfer(crb, masm); 728 masm.signx(asLongReg(src), asIntReg(dst)); 729 break; 730 case B2L: 731 masm.sll(asIntReg(src), 24, asLongReg(dst)); 732 delaySlotLir.emitControlTransfer(crb, masm); 733 masm.sra(asLongReg(dst), 24, asLongReg(dst)); 734 break; 735 case B2I: 736 masm.sll(asIntReg(src), 24, asIntReg(dst)); 737 delaySlotLir.emitControlTransfer(crb, masm); 738 masm.sra(asIntReg(dst), 24, asIntReg(dst)); 739 break; 740 case S2L: 741 masm.sll(asIntReg(src), 16, asLongReg(dst)); 742 delaySlotLir.emitControlTransfer(crb, masm); 743 masm.sra(asLongReg(dst), 16, asLongReg(dst)); 744 break; 745 case S2I: 746 masm.sll(asIntReg(src), 16, asIntReg(dst)); 747 delaySlotLir.emitControlTransfer(crb, masm); 748 masm.sra(asIntReg(dst), 16, asIntReg(dst)); 749 break; 750 case I2F: 751 delaySlotLir.emitControlTransfer(crb, masm); 752 masm.fitos(asFloatReg(src), asFloatReg(dst)); 753 break; 754 case F2D: 755 delaySlotLir.emitControlTransfer(crb, masm); 756 masm.fstod(asFloatReg(src), asDoubleReg(dst)); 757 break; 758 case F2L: 759 masm.fcmp(Fcc0, Fcmps, asFloatReg(src), asFloatReg(src)); 760 masm.fbpcc(F_Ordered, ANNUL, notOrdered, Fcc0, PREDICT_TAKEN); 761 masm.fstox(asFloatReg(src), asDoubleReg(dst)); 762 masm.fxtod(asRegister(dst), asRegister(dst)); 763 masm.fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)); 764 masm.bind(notOrdered); 765 break; 766 case F2I: 767 masm.fcmp(Fcc0, Fcmps, asFloatReg(src), asFloatReg(src)); 768 masm.fbpcc(F_Ordered, ANNUL, notOrdered, Fcc0, PREDICT_TAKEN); 769 masm.fstoi(asFloatReg(src), asFloatReg(dst)); 770 masm.fitos(asFloatReg(dst), asFloatReg(dst)); 771 masm.fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)); 772 masm.bind(notOrdered); 773 break; 774 case D2L: 775 masm.fcmp(Fcc0, Fcmpd, asDoubleReg(src), asDoubleReg(src)); 776 masm.fbpcc(F_Ordered, ANNUL, notOrdered, Fcc0, PREDICT_TAKEN); 777 masm.fdtox(asDoubleReg(src), asDoubleReg(dst)); 778 masm.fxtod(asDoubleReg(dst), asDoubleReg(dst)); 779 masm.fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)); 780 masm.bind(notOrdered); 781 break; 782 case D2I: 783 masm.fcmp(Fcc0, Fcmpd, asDoubleReg(src), asDoubleReg(src)); 784 masm.fbpcc(F_Ordered, ANNUL, notOrdered, Fcc0, PREDICT_TAKEN); 785 masm.fdtoi(asDoubleReg(src), asFloatReg(dst)); 786 masm.fitos(asFloatReg(dst), asFloatReg(dst)); 787 masm.fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)); 788 masm.bind(notOrdered); 789 break; 790 case FNEG: 791 delaySlotLir.emitControlTransfer(crb, masm); 792 masm.fnegs(asFloatReg(src), asFloatReg(dst)); 793 break; 794 case DNEG: 795 delaySlotLir.emitControlTransfer(crb, masm); 796 masm.fnegd(asDoubleReg(src), asDoubleReg(dst)); 797 break; 798 default: 799 throw JVMCIError.shouldNotReachHere("missing: " + opcode); 800 } 801 if (info != null) { 802 assert exceptionOffset != -1; 803 crb.recordImplicitException(exceptionOffset, info); 804 } 805 } 806 807 private static void verifyKind(SPARCArithmetic opcode, Value result, Value x, Value y) { 808 Kind rk; 809 Kind xk; 810 Kind yk; 811 Kind xsk; 812 Kind ysk; 813 814 switch (opcode) { 815 case IADD: 816 case IADDCC: 817 case ISUB: 818 case ISUBCC: 819 case IMUL: 820 case IMULCC: 821 case IDIV: 822 case IREM: 823 case IAND: 824 case IOR: 825 case IXOR: 826 case ISHL: 827 case ISHR: 828 case IUSHR: 829 case IUDIV: 830 case IUREM: 831 rk = result.getKind().getStackKind(); 832 xsk = x.getKind().getStackKind(); 833 ysk = y.getKind().getStackKind(); 834 boolean valid = false; 835 for (Kind k : new Kind[]{Kind.Int, Kind.Short, Kind.Byte, Kind.Char}) { 836 valid |= rk == k && xsk == k && ysk == k; 837 } 838 assert valid : "rk: " + rk + " xsk: " + xsk + " ysk: " + ysk; 839 break; 840 case LADD: 841 case LADDCC: 842 case LSUB: 843 case LSUBCC: 844 case LMUL: 845 case LMULCC: 846 case LDIV: 847 case LREM: 848 case LAND: 849 case LOR: 850 case LXOR: 851 case LUDIV: 852 case LUREM: 853 rk = result.getKind(); 854 xk = x.getKind(); 855 yk = y.getKind(); 856 assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long; 857 break; 858 case LSHL: 859 case LSHR: 860 case LUSHR: 861 rk = result.getKind(); 862 xk = x.getKind(); 863 yk = y.getKind(); 864 assert rk == Kind.Long && xk == Kind.Long && (yk == Kind.Int || yk == Kind.Long); 865 break; 866 case FADD: 867 case FSUB: 868 case FMUL: 869 case FDIV: 870 case FREM: 871 rk = result.getKind(); 872 xk = x.getKind(); 873 yk = y.getKind(); 874 assert (rk == Kind.Float || rk == Kind.Double) && xk == Kind.Float && yk == Kind.Float; 875 break; 876 case DAND: 877 case DADD: 878 case DSUB: 879 case DMUL: 880 case DDIV: 881 case DREM: 882 rk = result.getKind(); 883 xk = x.getKind(); 884 yk = y.getKind(); 885 assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double : "opcode=" + opcode + ", result kind=" + rk + ", x kind=" + xk + ", y kind=" + yk; 886 break; 887 default: 888 throw JVMCIError.shouldNotReachHere("missing: " + opcode); 889 } 890 } 891 892 public static final class MulHighOp extends SPARCLIRInstruction { 893 public static final LIRInstructionClass<MulHighOp> TYPE = LIRInstructionClass.create(MulHighOp.class); 894 public static final SizeEstimate SIZE = SizeEstimate.create(4); 895 896 @Opcode private final SPARCArithmetic opcode; 897 @Def({REG}) public AllocatableValue result; 898 @Alive({REG}) public AllocatableValue x; 899 @Alive({REG}) public AllocatableValue y; 900 @Temp({REG}) public AllocatableValue scratch; 901 902 public MulHighOp(SPARCArithmetic opcode, AllocatableValue x, AllocatableValue y, AllocatableValue result, AllocatableValue scratch) { 903 super(TYPE, SIZE); 904 this.opcode = opcode; 905 this.x = x; 906 this.y = y; 907 this.scratch = scratch; 908 this.result = result; 909 } 910 911 @Override 912 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { 913 assert isRegister(x) && isRegister(y) && isRegister(result) && isRegister(scratch); 914 switch (opcode) { 915 case IMUL: 916 masm.sra(asRegister(x), 0, asRegister(x)); 917 masm.sra(asRegister(y), 0, asRegister(y)); 918 masm.mulx(asIntReg(x), asIntReg(y), asIntReg(result)); 919 masm.srax(asIntReg(result), 32, asIntReg(result)); 920 break; 921 case IUMUL: 922 assert !asIntReg(scratch).equals(asIntReg(result)); 923 masm.srl(asIntReg(x), 0, asIntReg(scratch)); 924 masm.srl(asIntReg(y), 0, asIntReg(result)); 925 masm.mulx(asIntReg(result), asIntReg(scratch), asIntReg(result)); 926 masm.srlx(asIntReg(result), 32, asIntReg(result)); 927 break; 928 case LMUL: 929 assert !asLongReg(scratch).equals(asLongReg(result)); 930 masm.umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)); 931 932 masm.srlx(asLongReg(x), 63, asLongReg(scratch)); 933 masm.mulx(asLongReg(scratch), asLongReg(y), asLongReg(scratch)); 934 masm.sub(asLongReg(result), asLongReg(scratch), asLongReg(result)); 935 936 masm.srlx(asLongReg(y), 63, asLongReg(scratch)); 937 masm.mulx(asLongReg(scratch), asLongReg(x), asLongReg(scratch)); 938 masm.sub(asLongReg(result), asLongReg(scratch), asLongReg(result)); 939 break; 940 case LUMUL: 941 masm.umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)); 942 break; 943 default: 944 throw JVMCIError.shouldNotReachHere(); 945 } 946 } 947 } 948}