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