code: /**
   * Copyright (c) 2004-2005, Regents of the University of California
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * Neither the name of the University of California, Los Angeles nor the
   * names of its contributors may be used to endorse or promote products
   * derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  package avrora.arch.legacy;
  
  import java.util.HashMap;
  import java.util.HashSet;
  
  /**
   * The <code>LegacyRegister</code> class represents a register available on the AVR instruction set. All registers
   * in the instruction set architecture are represented as objects that have a name and a number. Those objects
   * are singletons and are public static final fields of this class.<br><br>
   * <p/>
   * Additionally, the <code>LegacyRegister</code> class contains sets of registers that are used in verifying the
   * operand constraints of each individual instruction as defined in the AVR instruction set reference. An
   * example of an operand constraint is that ldi (load immediate) takes as operands one of the general purpose
   * registers {r17...r31} and an immediate. Other instructions take certain subsets of the instructions. Those
   * register sets are allocated once here and are exposed as static fields in this class.
   *
   * @author Ben L. Titzer
   * @see LegacyOperand
   * @see LegacyInstr
   */
  public class LegacyRegister {
  
      private static final HashMap<String, LegacyRegister> registers = initializeRegisterMap();
  
      public static final LegacyRegister R0 = getRegisterByNumber(0);
      public static final LegacyRegister R1 = getRegisterByNumber(1);
      public static final LegacyRegister R2 = getRegisterByNumber(2);
      public static final LegacyRegister R3 = getRegisterByNumber(3);
      public static final LegacyRegister R4 = getRegisterByNumber(4);
      public static final LegacyRegister R5 = getRegisterByNumber(5);
      public static final LegacyRegister R6 = getRegisterByNumber(6);
      public static final LegacyRegister R7 = getRegisterByNumber(7);
      public static final LegacyRegister R8 = getRegisterByNumber(8);
      public static final LegacyRegister R9 = getRegisterByNumber(9);
      public static final LegacyRegister R10 = getRegisterByNumber(10);
      public static final LegacyRegister R11 = getRegisterByNumber(11);
      public static final LegacyRegister R12 = getRegisterByNumber(12);
      public static final LegacyRegister R13 = getRegisterByNumber(13);
      public static final LegacyRegister R14 = getRegisterByNumber(14);
      public static final LegacyRegister R15 = getRegisterByNumber(15);
      public static final LegacyRegister R16 = getRegisterByNumber(16);
      public static final LegacyRegister R17 = getRegisterByNumber(17);
      public static final LegacyRegister R18 = getRegisterByNumber(18);
      public static final LegacyRegister R19 = getRegisterByNumber(19);
      public static final LegacyRegister R20 = getRegisterByNumber(20);
      public static final LegacyRegister R21 = getRegisterByNumber(21);
      public static final LegacyRegister R22 = getRegisterByNumber(22);
      public static final LegacyRegister R23 = getRegisterByNumber(23);
      public static final LegacyRegister R24 = getRegisterByNumber(24);
      public static final LegacyRegister R25 = getRegisterByNumber(25);
      public static final LegacyRegister R26 = getRegisterByNumber(26);
      public static final LegacyRegister R27 = getRegisterByNumber(27);
      public static final LegacyRegister R28 = getRegisterByNumber(28);
      public static final LegacyRegister R29 = getRegisterByNumber(29);
      public static final LegacyRegister R30 = getRegisterByNumber(30);
      public static final LegacyRegister R31 = getRegisterByNumber(31);
  
      public static final LegacyRegister X = getRegisterByName("x");
      public static final LegacyRegister Y = getRegisterByName("y");
      public static final LegacyRegister Z = getRegisterByName("z");
  
      private static final LegacyRegister[] REGS_0_31 = {
          R0, R1, R2, R3, R4, R5, R6, R7,
          R8, R9, R10, R11, R12, R13, R14, R15,
          R16, R17, R18, R19, R20, R21, R22, R23,
          R24, R25, R26, R27, R28, R29, R30, R31
      };
      private static final LegacyRegister[] EREGS = {
          R0, R2, R4, R6, R8, R10, R12, R14,
          R16, R18, R20, R22, R24, R26, R28, R30,
      };
      private static final LegacyRegister[] REGS_16_31 = {
          R16, R17, R18, R19, R20, R21, R22, R23,
          R24, R25, R26, R27, R28, R29, R30, R31
      };
      private static final LegacyRegister[] REGS_16_23 = {
          R16, R17, R18, R19,
          R20, R21, R22, R23,
      };
      private static final LegacyRegister[] REGS_XYZ = {
          X, Y, Z
      };
      private static final LegacyRegister[] REGS_YZ = {
          Y, Z
      };
      private static final LegacyRegister[] REGS_Z = {
          Z
      };
      private static final LegacyRegister[] REGS_RDL = {
          R24, R26, R28, R30
      };
  
      public static final Set GPR_set = new Set(REGS_0_31);
      public static final Set HGPR_set = new Set(REGS_16_31);
      public static final Set MGPR_set = new Set(REGS_16_23);
      public static final Set EGPR_set = new Set(EREGS);
      public static final Set ADR_set = new Set(REGS_XYZ);
      public static final Set RDL_set = new Set(REGS_RDL);
      public static final Set YZ_set = new Set(REGS_YZ);
      public static final Set Z_set = new Set(REGS_Z);
  
      private static HashMap<String, LegacyRegister> initializeRegisterMap() {
          HashMap<String, LegacyRegister> map = new HashMap<String, LegacyRegister>();
  
          for (int cntr = 0; cntr < 32; cntr++) {
              LegacyRegister reg = new LegacyRegister("r" + cntr, cntr, 8);
              map.put("r" + cntr, reg);
              map.put("R" + cntr, reg);
          }
  
          LegacyRegister reg = new LegacyRegister("X", 26, 16);
          map.put("x", reg);
          map.put("X", reg);
  
          reg = new LegacyRegister("Y", 28, 16);
          map.put("y", reg);
          map.put("Y", reg);
  
          reg = new LegacyRegister("Z", 30, 16);
          map.put("z", reg);
          map.put("Z", reg);
  
          return map;
      }
  
      /**
       * The <code>getRegisterByName()</code> method retrieves a reference to the <code>LegacyRegister</code> instance
       * with the given string name. This method is not case sensitive.
       *
       * @param name the name of the register as a string
       * @return a reference to the <code>LegacyRegister</code> object representing the register if a register of that
       *         name exists; null otherwise
       */
      public static LegacyRegister getRegisterByName(String name) {
          return (LegacyRegister)registers.get(name);
      }
  
      /**
       * The <code>getRegisterByNumber()</code> method retrieves a reference to the <code>LegacyRegister</code>
       * instance with the given offset in the register file.
       *
       * @param num the integer number of the register to retrieve
       * @return a reference to the <code>LegacyRegister</code> object representing the chosen register
       */
      public static LegacyRegister getRegisterByNumber(int num) {
          return getRegisterByName("r" + num);
      }
  
  
      private final String name;
      private final int number;
      private final int width;
  
      private LegacyRegister(String nm, int num, int w) {
          name = nm;
          number = num;
          width = w;
      }
  
      /**
       * The <code>hashCode()</code> computes the hash code of this register so that registers can be inserted
       * in hashmaps and hashsets. This implementation of register simply uses the hash code of the name of the
       * register as its hash code.
       *
       * @return an integer that represents the hash code of this register
       */
      public int hashCode() {
          return name.hashCode();
      }
  
      /**
       * The <code>toString()</code> method coverts this register to a string. This implementation simply
       * returns the name of the register.
       *
       * @return a string representation of this register
       */
      public String toString() {
          return name;
      }
  
      /**
       * The <code>getName()</code> method returns the name of the instruction as a string.
       *
       * @return the name of the instruction
       */
      public String getName() {
          return name;
      }
  
      /**
       * The <code>getNumber()</code> method returns the "number" of this register, meaning the offset into the
       * register file.
       *
       * @return the number of this register
       */
      public int getNumber() {
          return number;
      }
  
      /**
       * The <code>getWidth()</code> method returns the width of the register in bits.
       *
       * @return the number of bits in this register
       */
      public int getWidth() {
          return width;
      }
  
      /**
       * The <code>nextRegister()</code> method returns a reference to the register that immediately follows
       * this register in the register file. This is needed when treating multiple registers as a single value,
       * etc.
       *
       * @return the register immediately following this register in the register file
       */
      public LegacyRegister nextRegister() {
          return REGS_0_31[number + 1];
      }
  
      /**
       * The <code>Set</code> class represents a set of registers. This is used to represent classes of
       * registers that are used as operands to various instructions. For example, an instruction might expect
       * one of its operands to be a general purpose register that has a number greater than 15; a set of those
       * registers can be constructed and then a membership test performed.
       * <p/>
       * In practice, the needed register sets are all allocated statically.
       */
      public static class Set {
  
          /**
           * The <code>contents</code> field stores a string that represents a summary of the registers that are
           * in this set. An example string for the even registers would be <code>"{r0, r2, ..., r30}"</code>.
           */
          public final String contents;
  
          private final HashSet<LegacyRegister> registerSet;
  
          /**
           * The constructor for the <code>Set</code> class takes a string that represents the contents of the
           * registers and an array of registers that are members of the set. It then constructs an internal
           * hash set for fast membership tests.
           *
           * @param regs an array of registers that are members of this set
           */
          Set(LegacyRegister[] regs) {
              registerSet = new HashSet<LegacyRegister>(2 * regs.length);
              for (int cntr = 0; cntr < regs.length; cntr++) {
                  registerSet.add(regs[cntr]);
              }
  
              StringBuffer buf = new StringBuffer("{");
              for (int cntr = 0; cntr < regs.length; cntr++) {
                  registerSet.add(regs[cntr]);
                  // abreviate large sets
                  if (cntr == 2 && regs.length > 4) buf.append("..., ");
                  // print first two, and last, or all if the set is fewer than five
                  if (cntr < 2 || cntr == regs.length - 1 || regs.length < 5) {
                      buf.append(regs[cntr]);
                      if (cntr < regs.length - 1) buf.append(", ");
                  }
              }
              buf.append('}');
              contents = buf.toString();
          }
  
          /**
           * The <code>contains()</code> method tests for membership. Given a register, it will return true if
           * that register is a member of this set, and false otherwise.
           *
           * @param reg the register to test membership of
           * @return true if the specified register is a member of this set; false otherwise
           */
          public boolean contains(LegacyRegister reg) {
              return registerSet.contains(reg);
          }
  
          /**
           * The <code>toString()</code> method converts this set to a string representation. In this
           * implementation, it simply returns the string representation of the contents.
           *
           * @return a string representation of this register set
           */
          public String toString() {
              return contents;
          }
      }
  
  }
  