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}