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