1 /* 2 * Copyright (c) 2011, 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 package com.oracle.graal.lir.ptx; 24 25 import static com.oracle.graal.api.code.ValueUtil.*; 26 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 27 28 import com.oracle.graal.api.code.*; 29 import com.oracle.graal.api.meta.*; 30 import com.oracle.graal.asm.ptx.*; 31 import com.oracle.graal.graph.*; 32 import com.oracle.graal.lir.asm.*; 33 import com.oracle.graal.nodes.calc.*; 34 35 public enum PTXCompare { 36 ICMP, LCMP, ACMP, FCMP, DCMP; 37 38 public static class CompareOp extends PTXLIRInstruction { 39 40 @Opcode private final PTXCompare opcode; 41 @Use({REG, STACK, CONST}) protected Value x; 42 @Use({REG, STACK, CONST}) protected Value y; 43 private final Condition condition; 44 45 public CompareOp(PTXCompare opcode, Condition condition, Value x, Value y) { 46 this.opcode = opcode; 47 this.condition = condition; 48 this.x = x; 49 this.y = y; 50 } 51 52 @Override 53 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 54 emit(tasm, masm, opcode, condition, x, y); 55 } 56 57 @Override 58 protected void verify() { 59 super.verify(); 60 assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || 61 (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) || 62 (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double); 63 } 64 } 65 66 public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) { 67 if (isConstant(x)) { 68 switch (opcode) { 69 case ICMP: 70 emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y)); 71 break; 72 case FCMP: 73 emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y)); 74 break; 75 case DCMP: 76 emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y)); 77 break; 78 default: 79 throw GraalInternalError.shouldNotReachHere(); 80 } 81 } else if (isConstant(y)) { 82 Register a = asIntReg(x); 83 int b = tasm.asIntConst(y); 84 switch (opcode) { 85 case ICMP: 86 emitCompareRegConst(masm, condition, a, b); 87 break; 88 case ACMP: 89 if (((Constant) y).isNull()) { 90 switch (condition) { 91 case EQ: 92 masm.setp_eq_s32(a, b); 93 break; 94 case NE: 95 masm.setp_ne_s32(a, b); 96 break; 97 default: 98 throw GraalInternalError.shouldNotReachHere(); 99 } 100 } else { 101 throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); 102 } 103 break; 104 default: 105 throw GraalInternalError.shouldNotReachHere(); 106 } 107 } else { 108 switch (opcode) { 109 case ICMP: 110 emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y)); 111 break; 112 case LCMP: 113 emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y)); 114 break; 115 case FCMP: 116 emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y)); 117 break; 118 case DCMP: 119 emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y)); 120 break; 121 default: 122 throw GraalInternalError.shouldNotReachHere("missing: " + opcode); 123 } 124 } 125 } 126 127 private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) { 128 switch (condition) { 129 case EQ: 130 masm.setp_eq_f32(a, b); 131 break; 132 case NE: 133 masm.setp_ne_f32(a, b); 134 break; 135 case LT: 136 masm.setp_lt_f32(a, b); 137 break; 138 case LE: 139 masm.setp_le_f32(a, b); 140 break; 141 case GT: 142 masm.setp_gt_f32(a, b); 143 break; 144 case GE: 145 masm.setp_ge_f32(a, b); 146 break; 147 default: 148 throw GraalInternalError.shouldNotReachHere(); 149 } 150 } 151 152 private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) { 153 switch (condition) { 154 case EQ: 155 masm.setp_eq_f64(a, b); 156 break; 157 case NE: 158 masm.setp_ne_f64(a, b); 159 break; 160 case LT: 161 masm.setp_lt_f64(a, b); 162 break; 163 case LE: 164 masm.setp_le_f64(a, b); 165 break; 166 case GT: 167 masm.setp_gt_f64(a, b); 168 break; 169 case GE: 170 masm.setp_ge_f64(a, b); 171 break; 172 default: 173 throw GraalInternalError.shouldNotReachHere(); 174 } 175 } 176 177 private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) { 178 switch (condition) { 179 case EQ: 180 masm.setp_eq_s32(a, b); 181 break; 182 case NE: 183 masm.setp_ne_s32(a, b); 184 break; 185 case LT: 186 masm.setp_lt_s32(a, b); 187 break; 188 case LE: 189 masm.setp_le_s32(a, b); 190 break; 191 case GT: 192 masm.setp_gt_s32(a, b); 193 break; 194 case GE: 195 masm.setp_ge_s32(a, b); 196 break; 197 case AT: 198 masm.setp_gt_u32(a, b); 199 break; 200 case AE: 201 masm.setp_ge_u32(a, b); 202 break; 203 case BT: 204 masm.setp_lt_u32(a, b); 205 break; 206 case BE: 207 masm.setp_le_u32(a, b); 208 break; 209 default: 210 throw GraalInternalError.shouldNotReachHere(); 211 } 212 } 213 214 private static void emitCompareRegConst(PTXAssembler masm, Condition condition, Register a, int b) { 215 switch (condition) { 216 case EQ: 217 masm.setp_eq_s32(a, b); 218 break; 219 case NE: 220 masm.setp_ne_s32(a, b); 221 break; 222 case LT: 223 masm.setp_lt_s32(a, b); 224 break; 225 case LE: 226 masm.setp_le_s32(a, b); 227 break; 228 case GT: 229 masm.setp_gt_s32(a, b); 230 break; 231 case GE: 232 masm.setp_ge_s32(a, b); 233 break; 234 case AT: 235 masm.setp_gt_u32(a, b); 236 break; 237 case AE: 238 masm.setp_ge_u32(a, b); 239 break; 240 case BT: 241 masm.setp_lt_u32(a, b); 242 break; 243 case BE: 244 masm.setp_le_u32(a, b); 245 break; 246 default: 247 throw GraalInternalError.shouldNotReachHere(); 248 } 249 } 250 251 private static void emitCompareRegReg(PTXAssembler masm, Condition condition, Register a, Register b) { 252 switch (condition) { 253 case EQ: 254 masm.setp_eq_s32(a, b); 255 break; 256 case NE: 257 masm.setp_ne_s32(a, b); 258 break; 259 case LT: 260 masm.setp_lt_s32(a, b); 261 break; 262 case LE: 263 masm.setp_le_s32(a, b); 264 break; 265 case GT: 266 masm.setp_gt_s32(a, b); 267 break; 268 case GE: 269 masm.setp_ge_s32(a, b); 270 break; 271 case AT: 272 masm.setp_gt_u32(a, b); 273 break; 274 case AE: 275 masm.setp_ge_u32(a, b); 276 break; 277 case BT: 278 masm.setp_lt_u32(a, b); 279 break; 280 case BE: 281 masm.setp_le_u32(a, b); 282 break; 283 default: 284 throw GraalInternalError.shouldNotReachHere(); 285 } 286 } 287 }