graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java

Print this page




  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 }