001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.ir.operand.ia32;
014
015import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.CONDITION;
016import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.EQ;
017import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.GE;
018import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.GT;
019import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LE;
020import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LGE;
021import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LGT;
022import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LLE;
023import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LLT;
024import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LT;
025import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.NE;
026import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.NO;
027import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.NS;
028import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.O;
029import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.PE;
030import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.PO;
031import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.S;
032
033import org.jikesrvm.compilers.opt.OptimizingCompilerException;
034import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
035import org.jikesrvm.compilers.opt.ir.operand.Operand;
036
037/**
038 * An IA32 condition operand
039 */
040public final class IA32ConditionOperand extends Operand {
041
042  /**
043   * Value of this operand (one of the ConditionCode constants operands
044   * defined in AssemblerConstants)
045   */
046  public byte value;
047
048  @Override
049  public Operand copy() {
050    return new IA32ConditionOperand(value);
051  }
052
053  @Override
054  public boolean similar(Operand op) {
055    return (op instanceof IA32ConditionOperand) && ((IA32ConditionOperand) op).value == value;
056  }
057
058  /**
059   * flip the direction of the condition
060   * @return this, mutated to flip value
061   */
062  public IA32ConditionOperand flipCode() {
063    switch (value) {
064      case O:   value =  NO; break;
065      case NO:  value =   O; break;
066      case LLT: value = LGE; break;
067      case LGE: value = LLT; break;
068      case EQ:  value =  NE; break;
069      case NE:  value =  EQ; break;
070      case LLE: value = LGT; break;
071      case LGT: value = LLE; break;
072      case S:   value =  NS; break;
073      case NS:  value =   S; break;
074      case PE:  value =  PO; break;
075      case PO:  value =  PE; break;
076      case LT:  value =  GE; break;
077      case GE:  value =  LT; break;
078      case LE:  value =  GT; break;
079      case GT:  value =  LE; break;
080      default:
081        OptimizingCompilerException.UNREACHABLE();
082    }
083    return this;
084  }
085
086  /**
087   * change the condition when operands are flipped
088   * @return this mutated to change value
089   */
090  public IA32ConditionOperand flipOperands() {
091    switch (value) {
092      case LLT: value = LGT; break;
093      case LGE: value = LLE; break;
094      case LLE: value = LGE; break;
095      case LGT: value = LLT; break;
096      case LT:  value =  GT; break;
097      case GE:  value =  LE; break;
098      case LE:  value =  GE; break;
099      case GT:  value =  LT; break;
100      default:
101        OptimizingCompilerException.TODO();
102    }
103    return this;
104  }
105
106  /**
107   * Constructs the IA32 Condition Operand that corresponds to the
108   * argument ConditionOperand.
109   *
110   * @param c the template
111   */
112  public IA32ConditionOperand(ConditionOperand c) {
113    translate(c);
114  }
115
116  public static IA32ConditionOperand EQ() {
117    return new IA32ConditionOperand(EQ);
118  }
119
120  public static IA32ConditionOperand NE() {
121    return new IA32ConditionOperand(NE);
122  }
123
124  public static IA32ConditionOperand LT() {
125    return new IA32ConditionOperand(LT);
126  }
127
128  public static IA32ConditionOperand LE() {
129    return new IA32ConditionOperand(LE);
130  }
131
132  public static IA32ConditionOperand GT() {
133    return new IA32ConditionOperand(GT);
134  }
135
136  public static IA32ConditionOperand GE() {
137    return new IA32ConditionOperand(GE);
138  }
139
140  public static IA32ConditionOperand O() {
141    return new IA32ConditionOperand(O);
142  }
143
144  public static IA32ConditionOperand NO() {
145    return new IA32ConditionOperand(NO);
146  }
147
148  public static IA32ConditionOperand LGT() {
149    return new IA32ConditionOperand(LGT);
150  }
151
152  public static IA32ConditionOperand LLT() {
153    return new IA32ConditionOperand(LLT);
154  }
155
156  public static IA32ConditionOperand LGE() {
157    return new IA32ConditionOperand(LGE);
158  }
159
160  public static IA32ConditionOperand LLE() {
161    return new IA32ConditionOperand(LLE);
162  }
163
164  public static IA32ConditionOperand PE() {
165    return new IA32ConditionOperand(PE);
166  }
167
168  public static IA32ConditionOperand PO() {
169    return new IA32ConditionOperand(PO);
170  }
171
172  private IA32ConditionOperand(byte c) {
173    value = c;
174  }
175
176  // translate from ConditionOperand: used during LIR => MIR translation
177  private void translate(ConditionOperand c) {
178    switch (c.value) {
179      case ConditionOperand.EQUAL:
180        value = EQ;
181        break;
182      case ConditionOperand.NOT_EQUAL:
183        value = NE;
184        break;
185      case ConditionOperand.LESS:
186        value = LT;
187        break;
188      case ConditionOperand.LESS_EQUAL:
189        value = LE;
190        break;
191      case ConditionOperand.GREATER:
192        value = GT;
193        break;
194      case ConditionOperand.GREATER_EQUAL:
195        value = GE;
196        break;
197      case ConditionOperand.HIGHER:
198        value = LGT;
199        break;
200      case ConditionOperand.LOWER:
201      case ConditionOperand.CARRY_FROM_ADD:
202      case ConditionOperand.BORROW_FROM_SUB:
203      case ConditionOperand.BORROW_FROM_RSUB:
204      case ConditionOperand.BIT_TEST:
205      case ConditionOperand.RBIT_TEST:
206        value = LLT;
207        break;
208      case ConditionOperand.HIGHER_EQUAL:
209      case ConditionOperand.NO_CARRY_FROM_ADD:
210      case ConditionOperand.NO_BORROW_FROM_SUB:
211      case ConditionOperand.NO_BORROW_FROM_RSUB:
212      case ConditionOperand.NO_BIT_TEST:
213      case ConditionOperand.NO_RBIT_TEST:
214        value = LGE;
215        break;
216      case ConditionOperand.LOWER_EQUAL:
217        value = LLE;
218        break;
219      case ConditionOperand.OVERFLOW_FROM_ADD:
220      case ConditionOperand.OVERFLOW_FROM_SUB:
221      case ConditionOperand.OVERFLOW_FROM_RSUB:
222      case ConditionOperand.OVERFLOW_FROM_MUL:
223        value =   O;
224        break;
225      case ConditionOperand.NO_OVERFLOW_FROM_ADD:
226      case ConditionOperand.NO_OVERFLOW_FROM_SUB:
227      case ConditionOperand.NO_OVERFLOW_FROM_RSUB:
228      case ConditionOperand.NO_OVERFLOW_FROM_MUL:
229        value =  NO;
230        break;
231      case ConditionOperand.CMPL_EQUAL:
232      case ConditionOperand.CMPL_GREATER:
233      case ConditionOperand.CMPG_LESS:
234      case ConditionOperand.CMPL_GREATER_EQUAL:
235      case ConditionOperand.CMPG_LESS_EQUAL:
236      case ConditionOperand.CMPL_NOT_EQUAL:
237      case ConditionOperand.CMPL_LESS:
238      case ConditionOperand.CMPG_GREATER_EQUAL:
239      case ConditionOperand.CMPG_GREATER:
240      case ConditionOperand.CMPL_LESS_EQUAL:
241        throw new Error("IA32ConditionOperand.translate: Complex operand can't be directly translated " + c);
242      default:
243        OptimizingCompilerException.UNREACHABLE();
244    }
245  }
246
247  // Returns the string representation of this operand.
248  @Override
249  public String toString() {
250    return CONDITION[value];
251  }
252
253}