1 /*
2  * Copyright (c) 2013, 2018, 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 
25 package org.graalvm.compiler.hotspot.sparc;
26 
27 import static jdk.vm.ci.code.ValueUtil.asRegister;
28 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR;
29 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL;
30 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
31 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN;
32 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
33 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_nz;
34 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z;
35 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
36 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
37 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
38 import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable;
39 
40 import org.graalvm.compiler.asm.Label;
41 import org.graalvm.compiler.asm.sparc.SPARCAddress;
42 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
43 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
44 import org.graalvm.compiler.core.common.CompressEncoding;
45 import org.graalvm.compiler.lir.LIRInstructionClass;
46 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
47 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
48 import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer;
49 import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction;
50 import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction;
51 
52 import jdk.vm.ci.code.Register;
53 import jdk.vm.ci.code.ValueUtil;
54 import jdk.vm.ci.hotspot.HotSpotConstant;
55 import jdk.vm.ci.meta.AllocatableValue;
56 import jdk.vm.ci.meta.Constant;
57 import jdk.vm.ci.sparc.SPARC;
58 
59 public class SPARCHotSpotMove {
60 
61     public static class LoadHotSpotObjectConstantInline extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction, LoadConstantOp {
62         public static final LIRInstructionClass<LoadHotSpotObjectConstantInline> TYPE = LIRInstructionClass.create(LoadHotSpotObjectConstantInline.class);
63 
64         public static final SizeEstimate SIZE = SizeEstimate.create(8);
65         private HotSpotConstant constant;
66         @Def({REG, STACK}) AllocatableValue result;
67 
LoadHotSpotObjectConstantInline(HotSpotConstant constant, AllocatableValue result)68         public LoadHotSpotObjectConstantInline(HotSpotConstant constant, AllocatableValue result) {
69             super(TYPE, SIZE);
70             this.constant = constant;
71             this.result = result;
72         }
73 
74         @Override
emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm)75         protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
76             crb.recordInlineDataInCode(constant);
77             if (constant.isCompressed()) {
78                 masm.setw(0, asRegister(result), true);
79             } else {
80                 masm.setx(0, asRegister(result), true);
81             }
82         }
83 
84         @Override
getResult()85         public AllocatableValue getResult() {
86             return result;
87         }
88 
89         @Override
getConstant()90         public Constant getConstant() {
91             return constant;
92         }
93     }
94 
95     public static class LoadHotSpotObjectConstantFromTable extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
96         public static final LIRInstructionClass<LoadHotSpotObjectConstantFromTable> TYPE = LIRInstructionClass.create(LoadHotSpotObjectConstantFromTable.class);
97 
98         public static final SizeEstimate SIZE = SizeEstimate.create(2, 8);
99         private final HotSpotConstant constant;
100         @Use({REG}) private AllocatableValue constantTableBase;
101         @Def({REG, STACK}) AllocatableValue result;
102 
LoadHotSpotObjectConstantFromTable(HotSpotConstant constant, AllocatableValue result, AllocatableValue constantTableBase)103         public LoadHotSpotObjectConstantFromTable(HotSpotConstant constant, AllocatableValue result, AllocatableValue constantTableBase) {
104             super(TYPE, SIZE);
105             this.constant = constant;
106             this.result = result;
107             this.constantTableBase = constantTableBase;
108         }
109 
110         @Override
emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm)111         protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
112             try (ScratchRegister scratch = masm.getScratchRegister()) {
113                 boolean isStack = ValueUtil.isStackSlot(result);
114                 Register register;
115                 if (isStack) {
116                     register = scratch.getRegister();
117                 } else {
118                     register = asRegister(result);
119                 }
120                 int bytes = loadFromConstantTable(crb, masm, asRegister(constantTableBase), constant, register, SPARCDelayedControlTransfer.DUMMY);
121                 if (isStack) {
122                     masm.st(register, (SPARCAddress) crb.asAddress(result), bytes);
123                 }
124             }
125         }
126     }
127 
128     public static final class CompressPointer extends SPARCLIRInstruction {
129         public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
130         public static final SizeEstimate SIZE = SizeEstimate.create(5);
131 
132         private final CompressEncoding encoding;
133         private final boolean nonNull;
134 
135         @Def({REG}) protected AllocatableValue result;
136         @Use({REG}) protected AllocatableValue input;
137         @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
138 
CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull)139         public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
140             super(TYPE, SIZE);
141             this.result = result;
142             this.input = input;
143             this.baseRegister = baseRegister;
144             this.encoding = encoding;
145             this.nonNull = nonNull;
146         }
147 
148         @Override
emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm)149         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
150             Register inputRegister = asRegister(input);
151             Register resReg = asRegister(result);
152             if (encoding.hasBase()) {
153                 Register baseReg = asRegister(baseRegister);
154                 if (!nonNull) {
155                     Label done = new Label();
156                     if (inputRegister.equals(resReg)) {
157                         BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, inputRegister, done);
158                         masm.sub(inputRegister, baseReg, resReg);
159                         masm.bind(done);
160                         if (encoding.getShift() != 0) {
161                             masm.srlx(resReg, encoding.getShift(), resReg);
162                         }
163                     } else {
164                         BPR.emit(masm, Rc_z, NOT_ANNUL, PREDICT_NOT_TAKEN, inputRegister, done);
165                         masm.mov(SPARC.g0, resReg);
166                         masm.sub(inputRegister, baseReg, resReg);
167                         if (encoding.getShift() != 0) {
168                             masm.srlx(resReg, encoding.getShift(), resReg);
169                         }
170                         masm.bind(done);
171                     }
172                 } else {
173                     masm.sub(inputRegister, baseReg, resReg);
174                     if (encoding.getShift() != 0) {
175                         masm.srlx(resReg, encoding.getShift(), resReg);
176                     }
177                 }
178             } else {
179                 if (encoding.getShift() != 0) {
180                     masm.srlx(inputRegister, encoding.getShift(), resReg);
181                 }
182             }
183         }
184     }
185 
186     public static final class UncompressPointer extends SPARCLIRInstruction {
187         public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
188         public static final SizeEstimate SIZE = SizeEstimate.create(4);
189 
190         private final CompressEncoding encoding;
191         private final boolean nonNull;
192 
193         @Def({REG}) protected AllocatableValue result;
194         @Use({REG}) protected AllocatableValue input;
195         @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
196 
UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull)197         public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
198             super(TYPE, SIZE);
199             this.result = result;
200             this.input = input;
201             this.baseRegister = baseRegister;
202             this.encoding = encoding;
203             this.nonNull = nonNull;
204         }
205 
206         @Override
emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm)207         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
208             Register inputRegister = asRegister(input);
209             Register resReg = asRegister(result);
210             Register baseReg = encoding.hasBase() ? asRegister(baseRegister) : null;
211             emitUncompressCode(masm, inputRegister, resReg, baseReg, encoding.getShift(), nonNull);
212         }
213 
emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull)214         public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
215             Register secondaryInput;
216             if (shift != 0) {
217                 masm.sllx(inputRegister, shift, resReg);
218                 secondaryInput = resReg;
219             } else {
220                 secondaryInput = inputRegister;
221             }
222 
223             if (baseReg != null) {
224                 if (nonNull) {
225                     masm.add(secondaryInput, baseReg, resReg);
226                 } else {
227                     Label done = new Label();
228                     BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, secondaryInput, done);
229                     masm.add(baseReg, secondaryInput, resReg);
230                     masm.bind(done);
231                 }
232             }
233         }
234     }
235 
236 }
237