1 /*
2 * Copyright (c) 2009, 2012, 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 com.oracle.graal.asm.hsail;
25
26 import com.oracle.graal.api.code.*;
27
28 import static com.oracle.graal.api.code.ValueUtil.*;
29 import com.oracle.graal.api.meta.*;
30 import com.oracle.graal.hsail.*;
31 import com.oracle.graal.graph.GraalInternalError;
32 import com.amd.okra.OkraUtil;
33
34 /**
35 * This class contains routines to emit HSAIL assembly code.
36 */
37 public class HSAILAssembler extends AbstractHSAILAssembler {
38
39 /**
40 * Stack size in bytes (used to keep track of spilling).
41 */
42 private int maxDataTypeSize;
43
44 /**
45 * Maximum stack offset used by a store operation.
46 */
47 private long maxStackOffset = 0;
48
49 public long upperBoundStackSize() {
50 return maxStackOffset + maxDataTypeSize;
51 }
52
53 public HSAILAssembler(TargetDescription target) {
54 super(target);
55 }
56
57 @Override
58 public HSAILAddress makeAddress(Register base, int displacement) {
59 return new HSAILAddress(base, displacement);
60 }
61
62 @Override
63 public HSAILAddress getPlaceholder() {
64 return null;
65 }
66
67 public final void undefined(String str) {
68 emitString("undefined operation " + str);
69 }
70
71 public final void exit() {
72 emitString("ret;" + "");
73 }
74
75 /**
76 * An Object is only moved into a register when it is a class constant (which is not really a
77 * constant because it can be moved by GC). Because we can't patch the HSAIL once it is
78 * finalized, we handle changes due to GC movement by dereferencing a global reference that is
79 * created by JNI since these JNI global references do not move.
80 */
81 public final void mov(Register a, Object obj) {
82 if (obj instanceof Class) {
83 Class<?> clazz = (Class<?>) obj;
84 long refHandle = OkraUtil.getRefHandle(clazz);
85 String className = clazz.getName();
86 String regName = "$d" + a.encoding();
87 emitString("mov_b64 " + regName + ", 0x" + Long.toHexString(refHandle) + "; // handle for " + className);
88 emitString("ld_global_u64 " + regName + ", [" + regName + "];");
89 } else {
90 throw GraalInternalError.shouldNotReachHere("mov from object not a class");
91 }
92
93 }
94
95 public final void emitMov(Value dst, Value src) {
96 if (isRegister(dst) && isConstant(src) && src.getKind().getStackKind() == Kind.Object) {
97 mov(asRegister(dst), (asConstant(src)).asObject());
98 } else {
99 String argtype = getArgType(dst).substring(1);
100 emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
101 }
102 }
103
104 public final void emitLoad(Value dest, HSAILAddress addr) {
105 emitString("ld_global_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapAddress(addr) + ";");
106 }
107
108 public final void emitSpillLoad(Value dest, Value src) {
109 emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapStackSlot(src) + ";");
110 }
111
112 public final void emitStore(Value src, HSAILAddress addr) {
113 emitString("st_global_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapAddress(addr) + ";");
114 }
115
116 public final void emitSpillStore(Value src, Value dest) {
117 int sizestored = getArgSize(src);
118 if (maxDataTypeSize < sizestored) {
119 maxDataTypeSize = sizestored;
120 }
121 int stackoffset = HSAIL.getStackOffset(dest);
122 if (maxStackOffset < stackoffset) {
123 maxStackOffset = stackoffset;
124 }
125 emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + HSAIL.mapStackSlot(dest) + ";");
126 }
127
128 public void cbr(String target1) {
129 emitString("cbr " + "$c0" + ", " + target1 + ";");
130 }
131
132 public int getArgSize(Value src) {
133 switch (src.getKind()) {
134 case Int:
135 case Float:
136 return 32;
137 case Double:
138 case Long:
139 case Object:
140 return 64;
141 default:
142 throw GraalInternalError.shouldNotReachHere();
143 }
144 }
145
146 public static final String getArgType(Value src) {
147 String prefix = "";
148 switch (src.getKind()) {
149 case Float:
150 prefix = "f32";
151 break;
152 case Double:
153 prefix = "f64";
154 break;
155 case Int:
156 prefix = "s32";
157 break;
158 case Long:
159 prefix = "s64";
160 break;
161 case Object:
162 prefix = "u64";
163 break;
164 default:
165 throw GraalInternalError.shouldNotReachHere();
166 }
167 return prefix;
168 }
169
170 public static final String getArgTypeForceUnsigned(Value src) {
171 switch (src.getKind()) {
172 case Int:
173 return "u32";
174 case Long:
175 case Object:
176 return "u64";
177 default:
178 throw GraalInternalError.shouldNotReachHere();
179 }
180 }
181
182 public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
183 String prefix = "cmp_" + condition + (unordered ? "u" : "") + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1));
184 emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";");
185 }
186
187 public void emitConvert(Value dest, Value src) {
188 String prefix = (getArgType(dest).equals("f32") && getArgType(src).equals("f64")) ? "cvt_near_" : "cvt_";
189 emitString(prefix + getArgType(dest) + "_" + getArgType(src) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";");
190 }
191
192 public void emitArg1(String mnemonic, Value dest, Value src) {
193 emitString(mnemonic + "_" + getArgType(src) + " " + HSAIL.mapRegister(dest) + ", " + mapRegOrConstToString(src) + ";" + "");
194 }
195
196 public static String mapAddress(HSAILAddress addr) {
197 return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]";
198 }
199
200 private static String mapRegOrConstToString(Value src) {
201 if (!isConstant(src)) {
202 return HSAIL.mapRegister(src);
203 } else {
204 Constant consrc = asConstant(src);
205 switch (src.getKind()) {
206 case Int:
207 return Integer.toString(consrc.asInt());
208 case Float:
209 return Float.toString(consrc.asFloat()) + "f";
210 case Double:
211 return Double.toString(consrc.asDouble());
212 case Long:
213 return Long.toString(consrc.asLong());
214 default:
215 throw GraalInternalError.shouldNotReachHere("unknown type: " + src);
216 }
217 }
218
219 }
220
221 public final void emit(String mnemonic, Value dest, Value src0, Value src1) {
222 String prefix = getArgType(dest);
223 emit(mnemonic + "_" + prefix, dest, "", src0, src1);
224 }
225
226 private void emit(String instr, Value dest, String controlRegString, Value src0, Value src1) {
227 assert (!isConstant(dest));
228 emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), controlRegString, mapRegOrConstToString(src0), mapRegOrConstToString(src1)));
229 }
230
231 public final void cmovCommon(Value dest, Value trueReg, Value falseReg, int width) {
232 String instr = (width == 32 ? "cmov_b32" : "cmov_b64");
233 emit(instr, dest, "$c0, ", trueReg, falseReg);
234 }
235
236 }