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 24 package org.graalvm.compiler.core.sparc; 25 26 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Add; 27 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Addcc; 28 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.And; 29 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Mulx; 30 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sdivx; 31 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sllx; 32 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sra; 33 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srax; 34 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srl; 35 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sub; 36 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc; 37 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Udivx; 38 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xnor; 39 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Faddd; 40 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fadds; 41 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtos; 42 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitod; 43 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitos; 44 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuld; 45 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuls; 46 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegd; 47 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegs; 48 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstod; 49 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fxtod; 50 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.UMulxhi; 51 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; 52 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; 53 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; 54 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 55 import static org.graalvm.compiler.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.BSF; 56 import static org.graalvm.compiler.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.IBSR; 57 import static org.graalvm.compiler.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.LBSR; 58 import static jdk.vm.ci.code.CodeUtil.mask; 59 import static jdk.vm.ci.meta.JavaConstant.forLong; 60 import static jdk.vm.ci.sparc.SPARC.g0; 61 import static jdk.vm.ci.sparc.SPARCKind.DOUBLE; 62 import static jdk.vm.ci.sparc.SPARCKind.SINGLE; 63 import static jdk.vm.ci.sparc.SPARCKind.WORD; 64 import static jdk.vm.ci.sparc.SPARCKind.XWORD; 65 66 import org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s; 67 import org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs; 68 import org.graalvm.compiler.core.common.LIRKind; 69 import org.graalvm.compiler.core.common.calc.FloatConvert; 70 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 71 import org.graalvm.compiler.debug.GraalError; 72 import org.graalvm.compiler.lir.ConstantValue; 73 import org.graalvm.compiler.lir.LIRFrameState; 74 import org.graalvm.compiler.lir.Variable; 75 import org.graalvm.compiler.lir.VirtualStackSlot; 76 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; 77 import org.graalvm.compiler.lir.sparc.SPARCAddressValue; 78 import org.graalvm.compiler.lir.sparc.SPARCArithmetic; 79 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.FloatConvertOp; 80 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.MulHighOp; 81 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.MulHighOp.MulHigh; 82 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.RemOp; 83 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.RemOp.Rem; 84 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.SPARCIMulccOp; 85 import org.graalvm.compiler.lir.sparc.SPARCArithmetic.SPARCLMulccOp; 86 import org.graalvm.compiler.lir.sparc.SPARCBitManipulationOp; 87 import org.graalvm.compiler.lir.sparc.SPARCMove.LoadOp; 88 import org.graalvm.compiler.lir.sparc.SPARCMove.MoveFpGp; 89 import org.graalvm.compiler.lir.sparc.SPARCMove.StoreConstantOp; 90 import org.graalvm.compiler.lir.sparc.SPARCMove.StoreOp; 91 import org.graalvm.compiler.lir.sparc.SPARCOP3Op; 92 import org.graalvm.compiler.lir.sparc.SPARCOPFOp; 93 94 import jdk.vm.ci.meta.AllocatableValue; 95 import jdk.vm.ci.meta.JavaConstant; 96 import jdk.vm.ci.meta.PlatformKind; 97 import jdk.vm.ci.meta.Value; 98 import jdk.vm.ci.meta.ValueKind; 99 import jdk.vm.ci.sparc.SPARC; 100 import jdk.vm.ci.sparc.SPARC.CPUFeature; 101 import jdk.vm.ci.sparc.SPARCKind; 102 103 /** 104 * This class implements the SPARC specific portion of the LIR generator. 105 */ 106 public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { 107 108 @Override 109 public SPARCLIRGenerator getLIRGen() { 110 return (SPARCLIRGenerator) super.getLIRGen(); 111 } 112 113 @Override 114 public Variable emitBitCount(Value operand) { 115 Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); 116 Value usedOperand = operand; 117 if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend 118 usedOperand = getLIRGen().newVariable(operand.getValueKind()); 119 getLIRGen().append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand)); 120 } 121 getLIRGen().append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result)); 122 return result; 123 } 124 125 @Override 126 public Variable emitBitScanForward(Value operand) { 127 Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); 128 getLIRGen().append(new SPARCBitManipulationOp(BSF, result, getLIRGen().asAllocatable(operand), getLIRGen())); 129 return result; 130 } 131 132 @Override 133 public Variable emitBitScanReverse(Value operand) { 134 Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); 135 if (operand.getPlatformKind() == SPARCKind.XWORD) { 136 getLIRGen().append(new SPARCBitManipulationOp(LBSR, result, getLIRGen().asAllocatable(operand), getLIRGen())); 137 } else { 138 getLIRGen().append(new SPARCBitManipulationOp(IBSR, result, getLIRGen().asAllocatable(operand), getLIRGen())); 139 } 140 return result; 141 } 142 143 @Override 144 public Value emitMathAbs(Value input) { 145 Variable result = getLIRGen().newVariable(LIRKind.combine(input)); 146 SPARCKind kind = (SPARCKind) input.getPlatformKind(); 147 Opfs opf; 148 switch (kind) { 149 case SINGLE: 150 opf = Opfs.Fabss; 151 break; 152 case DOUBLE: 153 opf = Opfs.Fabsd; 154 break; 155 default: 156 throw GraalError.shouldNotReachHere("Input kind: " + kind); 157 } 158 getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); 159 return result; 160 } 161 162 @Override 163 public Value emitMathSqrt(Value input) { 164 Variable result = getLIRGen().newVariable(LIRKind.combine(input)); 165 SPARCKind kind = (SPARCKind) input.getPlatformKind(); 166 Opfs opf; 167 switch (kind) { 168 case SINGLE: 169 opf = Opfs.Fsqrts; 170 break; 171 case DOUBLE: 172 opf = Opfs.Fsqrtd; 173 break; 174 default: 175 throw GraalError.shouldNotReachHere("Input kind: " + kind); 176 } 177 getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); 178 return result; 179 } 180 181 @Override 182 public Value emitNegate(Value input) { 183 PlatformKind inputKind = input.getPlatformKind(); 184 if (isNumericInteger(inputKind)) { 185 return emitUnary(Sub, input); 186 } else { 187 return emitUnary(inputKind.equals(DOUBLE) ? Fnegd : Fnegs, input); 188 } 189 } 190 191 @Override 192 public Value emitNot(Value input) { 193 return emitUnary(Xnor, input); 194 } 195 196 private Variable emitUnary(Opfs opf, Value input) { 197 Variable result = getLIRGen().newVariable(LIRKind.combine(input)); 198 getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); 199 return result; 200 } 201 202 private Variable emitUnary(Op3s op3, Value input) { 203 Variable result = getLIRGen().newVariable(LIRKind.combine(input)); 204 getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result)); 205 return result; 206 } 207 208 private Variable emitBinary(ValueKind<?> resultKind, Opfs opf, Value a, Value b) { 209 return emitBinary(resultKind, opf, a, b, null); 210 } 211 212 private Variable emitBinary(ValueKind<?> resultKind, Opfs opf, Value a, Value b, LIRFrameState state) { 213 Variable result = getLIRGen().newVariable(resultKind); 214 if (opf.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { 215 getLIRGen().append(new SPARCOPFOp(opf, b, a, result, state)); 216 } else { 217 getLIRGen().append(new SPARCOPFOp(opf, a, b, result, state)); 218 } 219 return result; 220 } 221 222 private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, int b) { 223 return emitBinary(resultKind, op3, a, new ConstantValue(LIRKind.value(WORD), JavaConstant.forInt(b))); 224 } 225 226 private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, Value b) { 227 return emitBinary(resultKind, op3, a, b, null); 228 } 229 230 private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, Value b, LIRFrameState state) { 231 Variable result = getLIRGen().newVariable(resultKind); 232 if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { 233 getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state)); 234 } else { 235 getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state)); 236 } 237 return result; 238 } 239 240 @Override 241 protected boolean isNumericInteger(PlatformKind kind) { 242 return ((SPARCKind) kind).isInteger(); 243 } 244 245 @Override 246 public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) { 247 if (isNumericInteger(a.getPlatformKind())) { 248 return emitBinary(resultKind, setFlags ? Addcc : Add, a, b); 249 } else { 250 boolean isDouble = a.getPlatformKind().equals(DOUBLE); 251 return emitBinary(resultKind, isDouble ? Faddd : Fadds, a, b); 252 } 253 } 254 255 @Override 256 public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) { 257 if (isNumericInteger(a.getPlatformKind())) { 258 return emitBinary(resultKind, setFlags ? Subcc : Sub, a, b); 259 } else { 260 boolean isDouble = a.getPlatformKind().equals(DOUBLE); 261 return emitBinary(resultKind, isDouble ? Opfs.Fsubd : Opfs.Fsubs, a, b); 262 } 263 } 264 265 @Override 266 public Variable emitMul(Value a, Value b, boolean setFlags) { 267 LIRKind resultKind = LIRKind.combine(a, b); 268 PlatformKind aKind = a.getPlatformKind(); 269 if (isNumericInteger(aKind)) { 270 if (setFlags) { 271 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); 272 if (aKind == XWORD) { 273 getLIRGen().append(new SPARCLMulccOp(result, getLIRGen().load(a), getLIRGen().load(b), getLIRGen())); 274 } else if (aKind == WORD) { 275 getLIRGen().append(new SPARCIMulccOp(result, getLIRGen().load(a), getLIRGen().load(b))); 276 } else { 277 throw GraalError.shouldNotReachHere(); 278 } 279 return result; 280 } else { 281 return emitBinary(resultKind, setFlags ? Op3s.Mulscc : Op3s.Mulx, a, b); 282 } 283 } else { 284 boolean isDouble = a.getPlatformKind().equals(DOUBLE); 285 return emitBinary(resultKind, isDouble ? Fmuld : Fmuls, a, b); 286 } 287 } 288 289 @Override 290 public Value emitMulHigh(Value a, Value b) { 291 MulHigh opcode; 292 switch (((SPARCKind) a.getPlatformKind())) { 293 case WORD: 294 opcode = MulHigh.IMUL; 295 break; 296 case XWORD: 297 opcode = MulHigh.LMUL; 298 break; 299 default: 300 throw GraalError.shouldNotReachHere(); 301 } 302 return emitMulHigh(opcode, a, b); 303 } 304 305 @Override 306 public Value emitUMulHigh(Value a, Value b) { 307 switch (((SPARCKind) a.getPlatformKind())) { 308 case WORD: 309 Value aExtended = emitBinary(LIRKind.combine(a), Srl, a, 0); 310 Value bExtended = emitBinary(LIRKind.combine(b), Srl, b, 0); 311 Value result = emitBinary(LIRKind.combine(a, b), Mulx, aExtended, bExtended); 312 return emitBinary(LIRKind.combine(a, b), Srax, result, WORD.getSizeInBits()); 313 case XWORD: 314 return emitBinary(LIRKind.combine(a, b), UMulxhi, a, b); 315 default: 316 throw GraalError.shouldNotReachHere(); 317 } 318 } 319 320 private Value emitMulHigh(MulHigh opcode, Value a, Value b) { 321 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); 322 MulHighOp mulHigh = new MulHighOp(opcode, getLIRGen().load(a), getLIRGen().load(b), result, getLIRGen().newVariable(LIRKind.combine(a, b))); 323 getLIRGen().append(mulHigh); 324 return result; 325 } 326 327 @Override 328 public Value emitDiv(Value a, Value b, LIRFrameState state) { 329 LIRKind resultKind = LIRKind.combine(a, b); 330 PlatformKind aKind = a.getPlatformKind(); 331 PlatformKind bKind = b.getPlatformKind(); 332 if (isJavaConstant(b) && asJavaConstant(b).isDefaultForKind()) { // Div by zero 333 Value zero = SPARC.g0.asValue(LIRKind.value(SPARCKind.WORD)); 334 return emitBinary(resultKind, Op3s.Sdivx, zero, zero, state); 335 } else if (isNumericInteger(aKind)) { 336 Value fixedA = emitSignExtend(a, aKind.getSizeInBytes() * 8, 64); 337 Value fixedB = emitSignExtend(b, bKind.getSizeInBytes() * 8, 64); 338 return emitBinary(resultKind, Op3s.Sdivx, fixedA, fixedB, state); 339 } else { 340 boolean isDouble = a.getPlatformKind().equals(DOUBLE); 341 return emitBinary(resultKind, isDouble ? Opfs.Fdivd : Opfs.Fdivs, a, b, state); 342 } 343 } 344 345 @Override 346 public Value emitRem(Value a, Value b, LIRFrameState state) { 347 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); 348 Value aLoaded; 349 Variable q1; // Intermediate values 350 Variable q2; 351 SPARCKind aKind = (SPARCKind) a.getPlatformKind(); 352 switch (aKind) { 353 case WORD: 354 // Sign extend a and b 355 Variable as = emitBinary(result.getValueKind(), Sra, a, g0.asValue(LIRKind.value(WORD))); 356 Variable bs = emitBinary(result.getValueKind(), Sra, b, g0.asValue(LIRKind.value(WORD))); 357 q1 = emitBinary(as.getValueKind(), Sdivx, as, bs, state); 358 q2 = emitBinary(q1.getValueKind(), Mulx, q1, bs); 359 result = emitSub(as, q2, false); 360 break; 361 case XWORD: 362 aLoaded = getLIRGen().load(a); // Reuse the loaded value 363 q1 = emitBinary(result.getValueKind(), Sdivx, aLoaded, b, state); 364 q2 = emitBinary(result.getValueKind(), Mulx, q1, b); 365 result = emitSub(aLoaded, q2, false); 366 break; 367 case SINGLE: 368 ForeignCallLinkage fremCall = getLIRGen().getForeignCalls().lookupForeignCall(ARITHMETIC_FREM); 369 result = getLIRGen().emitForeignCall(fremCall, state, a, b); 370 break; 371 case DOUBLE: 372 ForeignCallLinkage dremCall = getLIRGen().getForeignCalls().lookupForeignCall(ARITHMETIC_DREM); 373 result = getLIRGen().emitForeignCall(dremCall, state, a, b); 374 break; 375 default: 376 throw GraalError.shouldNotReachHere("missing: " + a.getPlatformKind()); 377 } 378 return result; 379 } 380 381 @Override 382 public Value emitURem(Value a, Value b, LIRFrameState state) { 383 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); 384 Variable scratch1 = getLIRGen().newVariable(LIRKind.combine(a, b)); 385 Variable scratch2 = getLIRGen().newVariable(LIRKind.combine(a, b)); 386 Rem opcode; 387 switch (((SPARCKind) a.getPlatformKind())) { 388 case WORD: 389 opcode = Rem.IUREM; 390 break; 391 case XWORD: 392 opcode = Rem.LUREM; 393 break; 394 default: 395 throw GraalError.shouldNotReachHere(); 396 } 397 getLIRGen().append(new RemOp(opcode, result, getLIRGen().load(a), getLIRGen().load(b), scratch1, scratch2, state)); 398 return result; 399 400 } 401 402 @Override 403 public Value emitUDiv(Value a, Value b, LIRFrameState state) { 404 Value actualA = a; 405 Value actualB = b; 406 switch (((SPARCKind) a.getPlatformKind())) { 407 case WORD: 408 actualA = emitZeroExtend(actualA, 32, 64); 409 actualB = emitZeroExtend(actualB, 32, 64); 410 break; 411 case XWORD: 412 break; 413 default: 414 throw GraalError.shouldNotReachHere(); 415 } 416 return emitBinary(LIRKind.combine(actualA, actualB), Udivx, actualA, actualB, state); 417 } 418 419 @Override 420 public Variable emitAnd(Value a, Value b) { 421 LIRKind resultKind = LIRKind.combine(a, b); 422 return emitBinary(resultKind, Op3s.And, a, b); 423 } 424 425 @Override 426 public Variable emitOr(Value a, Value b) { 427 LIRKind resultKind = LIRKind.combine(a, b); 428 return emitBinary(resultKind, Op3s.Or, a, b); 429 } 430 431 @Override 432 public Variable emitXor(Value a, Value b) { 433 LIRKind resultKind = LIRKind.combine(a, b); 434 return emitBinary(resultKind, Op3s.Xor, a, b); 435 } 436 437 @Override 438 public Variable emitShl(Value a, Value b) { 439 SPARCKind aKind = (SPARCKind) a.getPlatformKind(); 440 LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind); 441 Op3s op; 442 switch (aKind) { 443 case WORD: 444 op = Op3s.Sll; 445 break; 446 case XWORD: 447 op = Op3s.Sllx; 448 break; 449 default: 450 throw GraalError.shouldNotReachHere(String.format("Unsupported kind %s", aKind)); 451 } 452 return emitBinary(resultKind, op, a, b); 453 } 454 455 @Override 456 public Variable emitShr(Value a, Value b) { 457 SPARCKind aKind = (SPARCKind) a.getPlatformKind(); 458 LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind); 459 Op3s op; 460 switch (aKind) { 461 case WORD: 462 op = Op3s.Sra; 463 break; 464 case XWORD: 465 op = Op3s.Srax; 466 break; 467 default: 468 throw GraalError.shouldNotReachHere(); 469 } 470 return emitBinary(resultKind, op, a, b); 471 } 472 473 @Override 474 public Variable emitUShr(Value a, Value b) { 475 SPARCKind aKind = (SPARCKind) a.getPlatformKind(); 476 LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind); 477 Op3s op; 478 switch (aKind) { 479 case WORD: 480 op = Op3s.Srl; 481 break; 482 case XWORD: 483 op = Op3s.Srlx; 484 break; 485 default: 486 throw GraalError.shouldNotReachHere(); 487 } 488 return emitBinary(resultKind, op, a, b); 489 } 490 491 private AllocatableValue emitConvertMove(LIRKind kind, AllocatableValue input) { 492 Variable result = getLIRGen().newVariable(kind); 493 getLIRGen().emitMove(result, input); 494 return result; 495 } 496 497 @Override 498 public Value emitFloatConvert(FloatConvert op, Value inputVal) { 499 AllocatableValue input = getLIRGen().asAllocatable(inputVal); 500 Value result; 501 switch (op) { 502 case D2F: 503 result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(SINGLE)); 504 getLIRGen().append(new SPARCOPFOp(Fdtos, inputVal, result)); 505 break; 506 case F2D: 507 result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(DOUBLE)); 508 getLIRGen().append(new SPARCOPFOp(Fstod, inputVal, result)); 509 break; 510 case I2F: { 511 AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); 512 result = getLIRGen().newVariable(intEncodedFloatReg.getValueKind()); 513 moveBetweenFpGp(intEncodedFloatReg, input); 514 getLIRGen().append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result)); 515 break; 516 } 517 case I2D: { 518 // Unfortunately we must do int -> float -> double because fitod has float 519 // and double encoding in one instruction 520 AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); 521 result = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); 522 moveBetweenFpGp(convertedFloatReg, input); 523 getLIRGen().append(new SPARCOPFOp(Fitod, convertedFloatReg, result)); 524 break; 525 } 526 case L2D: { 527 AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); 528 moveBetweenFpGp(longEncodedDoubleReg, input); 529 AllocatableValue convertedDoubleReg = getLIRGen().newVariable(longEncodedDoubleReg.getValueKind()); 530 getLIRGen().append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg)); 531 result = convertedDoubleReg; 532 break; 533 } 534 case D2I: { 535 AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); 536 getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg)); 537 AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); 538 moveBetweenFpGp(convertedIntReg, convertedFloatReg); 539 result = convertedIntReg; 540 break; 541 } 542 case F2L: { 543 AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); 544 getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg)); 545 AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); 546 moveBetweenFpGp(convertedLongReg, convertedDoubleReg); 547 result = convertedLongReg; 548 break; 549 } 550 case F2I: { 551 AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); 552 getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg)); 553 AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); 554 moveBetweenFpGp(convertedIntReg, convertedFloatReg); 555 result = convertedIntReg; 556 break; 557 } 558 case D2L: { 559 AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); 560 getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg)); 561 AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); 562 moveBetweenFpGp(convertedLongReg, convertedDoubleReg); 563 result = convertedLongReg; 564 break; 565 } 566 case L2F: { 567 AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); 568 result = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); 569 moveBetweenFpGp(convertedDoubleReg, input); 570 getLIRGen().append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result)); 571 break; 572 } 573 default: 574 throw GraalError.shouldNotReachHere(); 575 } 576 return result; 577 } 578 579 protected VirtualStackSlot getTempSlot(LIRKind kind) { 580 return getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(kind); 581 } 582 583 private void moveBetweenFpGp(AllocatableValue dst, AllocatableValue src) { 584 AllocatableValue tempSlot; 585 PlatformKind dstKind = dst.getPlatformKind(); 586 PlatformKind srcKind = src.getPlatformKind(); 587 if (getLIRGen().getArchitecture().getFeatures().contains(CPUFeature.VIS3) && !(srcKind == WORD && dstKind == SINGLE) && !(srcKind == SINGLE && dstKind == WORD)) { 588 tempSlot = AllocatableValue.ILLEGAL; 589 } else { 590 tempSlot = getTempSlot(LIRKind.value(XWORD)); 591 } 592 getLIRGen().append(new MoveFpGp(dst, src, tempSlot)); 593 } 594 595 @Override 596 public Value emitNarrow(Value inputVal, int bits) { 597 if (inputVal.getPlatformKind() == XWORD && bits <= 32) { 598 LIRKind resultKind = LIRKind.combine(inputVal).changeType(WORD); 599 Variable result = getLIRGen().newVariable(resultKind); 600 getLIRGen().emitMove(result, inputVal); 601 return result; 602 } else { 603 return inputVal; 604 } 605 } 606 607 @Override 608 public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { 609 assert fromBits <= toBits && toBits <= XWORD.getSizeInBits(); 610 LIRKind shiftKind = LIRKind.value(WORD); 611 LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? XWORD : WORD); 612 Value result; 613 int shiftCount = XWORD.getSizeInBits() - fromBits; 614 if (fromBits == toBits) { 615 result = inputVal; 616 } else if (isJavaConstant(inputVal)) { 617 JavaConstant javaConstant = asJavaConstant(inputVal); 618 long constant; 619 if (javaConstant.isNull()) { 620 constant = 0; 621 } else { 622 constant = javaConstant.asLong(); 623 } 624 return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); 625 } else if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { 626 result = getLIRGen().newVariable(resultKind); 627 getLIRGen().append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result)); 628 } else { 629 Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); 630 result = getLIRGen().newVariable(resultKind); 631 getLIRGen().append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); 632 getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); 633 } 634 return result; 635 } 636 637 @Override 638 public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { 639 assert fromBits <= toBits && toBits <= 64; 640 if (fromBits == toBits) { 641 return inputVal; 642 } 643 Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); 644 if (fromBits == 32) { 645 getLIRGen().append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result)); 646 } else { 647 Value mask = getLIRGen().emitConstant(LIRKind.value(XWORD), forLong(mask(fromBits))); 648 getLIRGen().append(new SPARCOP3Op(And, inputVal, mask, result)); 649 } 650 return result; 651 } 652 653 @Override 654 public AllocatableValue emitReinterpret(LIRKind to, Value inputVal) { 655 SPARCKind fromKind = (SPARCKind) inputVal.getPlatformKind(); 656 SPARCKind toKind = (SPARCKind) to.getPlatformKind(); 657 AllocatableValue input = getLIRGen().asAllocatable(inputVal); 658 Variable result = getLIRGen().newVariable(to); 659 // These cases require a move between CPU and FPU registers: 660 if (fromKind.isFloat() != toKind.isFloat()) { 661 moveBetweenFpGp(result, input); 662 return result; 663 } else { 664 // Otherwise, just emit an ordinary move instruction. 665 // Instructions that move or generate 32-bit register values also set the upper 32 666 // bits of the register to zero. 667 // Consequently, there is no need for a special zero-extension move. 668 return emitConvertMove(to, input); 669 } 670 } 671 672 @Override 673 public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) { 674 SPARCAddressValue loadAddress = getLIRGen().asAddressValue(address); 675 Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind)); 676 getLIRGen().append(new LoadOp(kind.getPlatformKind(), result, loadAddress, state)); 677 return result; 678 } 679 680 @Override 681 public void emitStore(ValueKind<?> kind, Value address, Value inputVal, LIRFrameState state) { 682 SPARCAddressValue storeAddress = getLIRGen().asAddressValue(address); 683 if (isJavaConstant(inputVal)) { 684 JavaConstant c = asJavaConstant(inputVal); 685 if (c.isDefaultForKind()) { 686 getLIRGen().append(new StoreConstantOp(kind.getPlatformKind(), storeAddress, c, state)); 687 return; 688 } 689 } 690 Variable input = getLIRGen().load(inputVal); 691 getLIRGen().append(new StoreOp(kind.getPlatformKind(), storeAddress, input, state)); 692 } 693 }