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 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 } | 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 String regName = "$d" + a.encoding(); 83 if (obj instanceof Class) { 84 Class<?> clazz = (Class<?>) obj; 85 long refHandle = OkraUtil.getRefHandle(clazz); 86 String className = clazz.getName(); 87 emitString("mov_b64 " + regName + ", 0x" + Long.toHexString(refHandle) + "; // handle for " + className); 88 emitString("ld_global_u64 " + regName + ", [" + regName + "];"); 89 } else if (obj == null) { 90 emitString("mov_b64 " + regName + ", 0x0; // null object"); 91 } else { 92 throw GraalInternalError.shouldNotReachHere("mov from object not a class"); 93 } 94 95 } 96 97 public final void emitMov(Value dst, Value src) { 98 if (isRegister(dst) && isConstant(src) && src.getKind().getStackKind() == Kind.Object) { 99 mov(asRegister(dst), (asConstant(src)).asObject()); 100 } else { 101 String argtype = getArgType(dst).substring(1); 102 emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";"); 103 } 104 } 105 106 private void emitAddrOp(String instr, Value reg, HSAILAddress addr) { 107 emitString(instr + " " + HSAIL.mapRegister(reg) + ", " + mapAddress(addr) + ";"); 108 } 109 110 public final void emitLoad(Value dest, HSAILAddress addr) { 111 emitLoad(dest, addr, getArgType(dest)); 112 } 113 114 public final void emitLoad(Value dest, HSAILAddress addr, String argTypeStr) { 115 emitAddrOp("ld_global_" + argTypeStr, dest, addr); 116 } 117 118 public final void emitLda(Value dest, HSAILAddress addr) { 119 emitAddrOp("lda_global_u64", dest, addr); 120 } 121 122 public final void emitStore(Value src, HSAILAddress addr) { 123 emitStore(src, addr, getArgType(src)); 124 } 125 126 public final void emitStore(Value dest, HSAILAddress addr, String argTypeStr) { 127 emitAddrOp("st_global_" + argTypeStr, dest, addr); 128 } 129 130 public final void emitSpillLoad(Value dest, Value src) { 131 emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSize(dest)) + ";"); 132 } 133 134 public final void emitSpillStore(Value src, Value dest) { 135 int sizestored = getArgSize(src); 136 if (maxDataTypeSize < sizestored) { 137 maxDataTypeSize = sizestored; 138 } 139 int stackoffset = HSAIL.getStackOffset(dest); 140 if (maxStackOffset < stackoffset) { 141 maxStackOffset = stackoffset; 142 } 143 emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSize(src)) + ";"); 144 } 145 146 /** 147 * The mapping to stack slots is always relative to the beginning 148 * of the spillseg. HSAIL.getStackOffset returns the positive 149 * version of the originally negative offset. Then we back up 150 * from that by the argSize in bytes. This ensures that slots of 151 * different size do not overlap, even though we have converted 152 * from negative to positive offsets. 153 */ 154 public static String mapStackSlot(Value reg, int argSize) { 155 long offset = HSAIL.getStackOffset(reg); 156 int argSizeBytes = argSize / 8; 157 return "[%spillseg]" + "[" + (offset - argSizeBytes) + "]"; 158 } 159 160 public void cbr(String target1) { 161 emitString("cbr " + "$c0" + ", " + target1 + ";"); 162 } 163 164 public int getArgSize(Value src) { 165 switch (src.getKind()) { 166 case Int: 167 case Float: 168 return 32; 169 case Double: 170 case Long: 171 case Object: 172 return 64; 173 default: 174 throw GraalInternalError.shouldNotReachHere(); 175 } 176 } 177 196 default: 197 throw GraalInternalError.shouldNotReachHere(); 198 } 199 return prefix; 200 } 201 202 public static final String getArgTypeForceUnsigned(Value src) { 203 switch (src.getKind()) { 204 case Int: 205 return "u32"; 206 case Long: 207 case Object: 208 return "u64"; 209 default: 210 throw GraalInternalError.shouldNotReachHere(); 211 } 212 } 213 214 public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) { 215 String prefix = "cmp_" + condition + (unordered ? "u" : "") + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1)); 216 String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) 217 && (asConstant(src1).asObject() == null) ? " // null test " : ""); 218 emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment); 219 } 220 221 public void emitConvert(Value dest, Value src) { 222 String prefix = (getArgType(dest).equals("f32") && getArgType(src).equals("f64")) ? "cvt_near_" : "cvt_"; 223 emitString(prefix + getArgType(dest) + "_" + getArgType(src) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); 224 } 225 226 public void emitArg1(String mnemonic, Value dest, Value src) { 227 emitString(mnemonic + "_" + getArgType(src) + " " + HSAIL.mapRegister(dest) + ", " + mapRegOrConstToString(src) + ";" + ""); 228 } 229 230 public static String mapAddress(HSAILAddress addr) { 231 return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]"; 232 } 233 234 private static String mapRegOrConstToString(Value src) { 235 if (!isConstant(src)) { 236 return HSAIL.mapRegister(src); 237 } else { 238 Constant consrc = asConstant(src); 239 switch (src.getKind()) { 240 case Int: 241 return Integer.toString(consrc.asInt()); 242 case Float: 243 return Float.toString(consrc.asFloat()) + "f"; 244 case Double: 245 return Double.toString(consrc.asDouble()); 246 case Long: 247 return "0x" + Long.toHexString(consrc.asLong()); 248 case Object: 249 Object obj = consrc.asObject(); 250 if (obj == null) { 251 return "0"; 252 } else { 253 throw GraalInternalError.shouldNotReachHere("unknown type: " + src); 254 } 255 default: 256 throw GraalInternalError.shouldNotReachHere("unknown type: " + src); 257 } 258 } 259 260 } 261 262 public final void emit(String mnemonic, Value dest, Value src0, Value src1) { 263 String prefix = getArgType(dest); 264 emit(mnemonic + "_" + prefix, dest, "", src0, src1); 265 } 266 267 public final void emitForceUnsigned(String mnemonic, Value dest, Value src0, Value src1) { 268 String prefix = getArgTypeForceUnsigned(dest); 269 emit(mnemonic + "_" + prefix, dest, "", src0, src1); 270 } 271 272 273 private void emit(String instr, Value dest, String controlRegString, Value src0, Value src1) { 274 assert (!isConstant(dest)); 275 emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), controlRegString, mapRegOrConstToString(src0), mapRegOrConstToString(src1))); 276 } 277 278 private void emit(String instr, Value dest, Value src0, Value src1, Value src2) { 279 assert (!isConstant(dest)); 280 emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0), 281 mapRegOrConstToString(src1), mapRegOrConstToString(src2))); 282 } 283 284 285 public final void cmovCommon(Value dest, Value trueReg, Value falseReg, int width) { 286 String instr = (width == 32 ? "cmov_b32" : "cmov_b64"); 287 emit(instr, dest, "$c0, ", trueReg, falseReg); 288 } 289 290 291 /** 292 * Emit code to build a 64-bit pointer from a compressed-oop and the associated base and shift. 293 * We only emit this if base and shift are not both zero. 294 */ 295 public void emitCompressedOopDecode(Value result, long narrowOopBase, int narrowOopShift) { 296 if (narrowOopBase == 0) { 297 emit("shl", result, result, Constant.forInt(narrowOopShift)); 298 } else if (narrowOopShift == 0) { 299 // only use add if result is not starting as null (unsigned compare) 300 emitCompare(result, Constant.forLong(0), "eq", false, true); 301 emit("add", result, result, Constant.forLong(narrowOopBase)); 302 cmovCommon(result, Constant.forLong(0), result, 64); 303 } else { 304 // only use mad if result is not starting as null (unsigned compare) 305 emitCompare(result, Constant.forLong(0), "eq", false, true); 306 emit("mad_u64 ", result, result, Constant.forInt(1 << narrowOopShift), Constant.forLong(narrowOopBase)); 307 cmovCommon(result, Constant.forLong(0), result, 64); 308 } 309 } 310 311 /** 312 * Emit code to build a 32-bit compressed pointer from a full 313 * 64-bit pointer using the associated base and shift. We only 314 * emit this if base and shift are not both zero. 315 */ 316 public void emitCompressedOopEncode(Value result, long narrowOopBase, int narrowOopShift) { 317 if (narrowOopBase != 0) { 318 // only use sub if result is not starting as null (unsigned compare) 319 emitCompare(result, Constant.forLong(0), "eq", false, true); 320 emit("sub", result, result, Constant.forLong(narrowOopBase)); 321 cmovCommon(result, Constant.forLong(0), result, 64); 322 } 323 if (narrowOopShift != 0) { 324 emit("shr", result, result, Constant.forInt(narrowOopShift)); 325 } 326 } 327 328 public void emitComment(String comment) { 329 emitString(comment); 330 } 331 } |