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