1 /*
2 * Copyright (c) 2014, 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.lir.sparc;
26
27 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
28 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
30 import static org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer.DUMMY;
31
32 import java.util.Arrays;
33
34 import jdk.internal.vm.compiler.collections.EconomicSet;
35 import org.graalvm.compiler.asm.sparc.SPARCAddress;
36 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
37 import org.graalvm.compiler.lir.LIRInstructionClass;
38 import org.graalvm.compiler.lir.LIRValueUtil;
39 import org.graalvm.compiler.lir.Opcode;
40 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
41 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
42 import org.graalvm.compiler.lir.framemap.FrameMap;
43
44 import jdk.vm.ci.code.Register;
45 import jdk.vm.ci.code.RegisterSaveLayout;
46 import jdk.vm.ci.code.RegisterValue;
47 import jdk.vm.ci.code.StackSlot;
48 import jdk.vm.ci.meta.AllocatableValue;
49 import jdk.vm.ci.sparc.SPARC;
50
51 /**
52 * Saves registers to stack slots.
53 */
54 @Opcode("SAVE_REGISTER")
55 public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
56 public static final LIRInstructionClass<SPARCSaveRegistersOp> TYPE = LIRInstructionClass.create(SPARCSaveRegistersOp.class);
57 public static final Register RETURN_REGISTER_STORAGE = SPARC.d62;
58 public static final SizeEstimate SIZE = SizeEstimate.create(32);
59 /**
60 * The registers (potentially) saved by this operation.
61 */
62 protected final Register[] savedRegisters;
63
64 /**
65 * The slots to which the registers are saved.
66 */
67 @Def(STACK) protected final AllocatableValue[] slots;
68
69 /**
70 * Specifies if {@link #remove(EconomicSet)} should have an effect.
71 */
72 protected final boolean supportsRemove;
73
74 /**
75 *
76 * @param savedRegisters the registers saved by this operation which may be subject to
77 * {@linkplain #remove(EconomicSet) pruning}
78 * @param savedRegisterLocations the slots to which the registers are saved
79 * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned}
80 */
81 public SPARCSaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
82 super(TYPE, SIZE);
83 assert Arrays.asList(savedRegisterLocations).stream().allMatch(LIRValueUtil::isVirtualStackSlot);
84 this.savedRegisters = savedRegisters;
85 this.slots = savedRegisterLocations;
86 this.supportsRemove = supportsRemove;
87 }
88
89 @Override
90 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
91 // Can be used with VIS3
92 // new Movxtod(SPARC.i0, RETURN_REGISTER_STORAGE).emit(masm);
93 // We abuse the first stackslot for transferring i0 to return_register_storage
94 // assert slots.length >= 1;
95 SPARCAddress slot0Address = (SPARCAddress) crb.asAddress(slots[0]);
96 masm.stx(SPARC.i0, slot0Address);
97 masm.lddf(slot0Address, RETURN_REGISTER_STORAGE);
98
99 // Now save the registers
100 for (int i = 0; i < savedRegisters.length; i++) {
101 if (savedRegisters[i] != null) {
102 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
103 Register savedRegister = savedRegisters[i];
104 StackSlot slot = asStackSlot(slots[i]);
105 SPARCAddress slotAddress = (SPARCAddress) crb.asAddress(slot);
106 RegisterValue input = savedRegister.asValue(slot.getValueKind());
107 SPARCMove.emitStore(input, slotAddress, slot.getPlatformKind(), DUMMY, null, crb, masm);
108 }
109 }
110 }
111
112 public AllocatableValue[] getSlots() {
113 return slots;
114 }
115
116 @Override
117 public boolean supportsRemove() {
118 return supportsRemove;
119 }
120
121 @Override
122 public int remove(EconomicSet<Register> doNotSave) {
123 if (!supportsRemove) {
124 throw new UnsupportedOperationException();
125 }
126 return prune(doNotSave, savedRegisters);
127 }
128
129 static int prune(EconomicSet<Register> toRemove, Register[] registers) {
130 int pruned = 0;
131 for (int i = 0; i < registers.length; i++) {
132 if (registers[i] != null) {
133 if (toRemove.contains(registers[i])) {
134 registers[i] = null;
135 pruned++;
136 }
137 }
138 }
139 return pruned;
140 }
141
142 @Override
143 public RegisterSaveLayout getMap(FrameMap frameMap) {
144 int total = 0;
145 for (int i = 0; i < savedRegisters.length; i++) {
146 if (savedRegisters[i] != null) {
147 total++;
148 }
149 }
150 Register[] keys = new Register[total];
151 int[] values = new int[total];
152 if (total != 0) {
153 int mapIndex = 0;
154 for (int i = 0; i < savedRegisters.length; i++) {
155 if (savedRegisters[i] != null) {
156 keys[mapIndex] = savedRegisters[i];
157 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
158 StackSlot slot = asStackSlot(slots[i]);
159 values[mapIndex] = indexForStackSlot(frameMap, slot);
160 mapIndex++;
161 }
162 }
163 assert mapIndex == total;
164 }
165 return new RegisterSaveLayout(keys, values);
166 }
167
168 /**
169 * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack
170 * slots in the reference map.
171 *
172 * @param slot a stack slot
173 * @return the index of the stack slot
174 */
175 private static int indexForStackSlot(FrameMap frameMap, StackSlot slot) {
176 assert frameMap.offsetForStackSlot(slot) % frameMap.getTarget().wordSize == 0;
177 int value = frameMap.offsetForStackSlot(slot) / frameMap.getTarget().wordSize;
178 return value;
179 }
180 }
|
1 /*
2 * Copyright (c) 2014, 2019, 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.lir.sparc;
26
27 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
28 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
29 import static org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer.DUMMY;
30
31 import jdk.internal.vm.compiler.collections.EconomicSet;
32 import org.graalvm.compiler.asm.sparc.SPARCAddress;
33 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
34 import org.graalvm.compiler.lir.LIRInstructionClass;
35 import org.graalvm.compiler.lir.Opcode;
36 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
37 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
38
39 import jdk.vm.ci.code.Register;
40 import jdk.vm.ci.code.RegisterValue;
41 import jdk.vm.ci.code.StackSlot;
42 import jdk.vm.ci.meta.AllocatableValue;
43 import jdk.vm.ci.sparc.SPARC;
44
45 /**
46 * Saves registers to stack slots.
47 */
48 @Opcode("SAVE_REGISTER")
49 public class SPARCSaveRegistersOp extends SaveRegistersOp implements SPARCLIRInstructionMixin {
50 public static final LIRInstructionClass<SPARCSaveRegistersOp> TYPE = LIRInstructionClass.create(SPARCSaveRegistersOp.class);
51 public static final Register RETURN_REGISTER_STORAGE = SPARC.d62;
52 public static final SizeEstimate SIZE = SizeEstimate.create(32);
53 private final SPARCLIRInstructionMixinStore store;
54
55 /**
56 *
57 * @param savedRegisters the registers saved by this operation which may be subject to
58 * {@linkplain #remove(EconomicSet) pruning}
59 * @param savedRegisterLocations the slots to which the registers are saved
60 */
61 public SPARCSaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
62 super(TYPE, savedRegisters, savedRegisterLocations);
63 this.store = new SPARCLIRInstructionMixinStore(SIZE);
64 }
65
66 @Override
67 public void emitCode(CompilationResultBuilder crb) {
68 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
69 // Can be used with VIS3
70 // new Movxtod(SPARC.i0, RETURN_REGISTER_STORAGE).emit(masm);
71 // We abuse the first stackslot for transferring i0 to return_register_storage
72 // assert slots.length >= 1;
73 SPARCAddress slot0Address = (SPARCAddress) crb.asAddress(slots[0]);
74 masm.stx(SPARC.i0, slot0Address);
75 masm.lddf(slot0Address, RETURN_REGISTER_STORAGE);
76
77 // Now save the registers
78 for (int i = 0; i < savedRegisters.length; i++) {
79 if (savedRegisters[i] != null) {
80 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
81 Register savedRegister = savedRegisters[i];
82 StackSlot slot = asStackSlot(slots[i]);
83 SPARCAddress slotAddress = (SPARCAddress) crb.asAddress(slot);
84 RegisterValue input = savedRegister.asValue(slot.getValueKind());
85 SPARCMove.emitStore(input, slotAddress, slot.getPlatformKind(), DUMMY, null, crb, masm);
86 }
87 }
88 }
89
90 @Override
91 public SPARCLIRInstructionMixinStore getSPARCLIRInstructionStore() {
92 return store;
93 }
94 }
|