gt:         switch (state) {
context: /*
   * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  package com.sun.max.asm;
  
  import com.sun.max.program.*;
  
  /**
   * Assembler labels for symbolic addressing.
   *
   * This class provides combined functionality for both 32-bit and 64-bit address spaces.
   * The respective assembler narrows the usable interface to either.
   *
   * @see Assembler32
   * @see Assembler64
   */
  public final class Label implements Argument {
  
      public enum State {
          UNASSIGNED, BOUND, FIXED_32, FIXED_64;
      }
  
      protected State state = State.UNASSIGNED;
  
      public static Label createBoundLabel(int position) {
          final Label label = new Label();
          label.bind(position);
          return label;
      }
  
      public Label() {
      }
  
      public State state() {
          return state;
      }
  
      private int position;
  
      /**
       * Must only be called when the label is bound!
       */
      public int position() throws AssemblyException {
          if (state != State.BOUND) {
              throw new AssemblyException("unassigned or unbound label");
          }
          return position;
      }
  
      /**
       * Binds this label to a position in the assembler's instruction stream that represents the start of an instruction.
       * The assembler may update the position if any emitted instructions change lengths, so that this label keeps
       * denoting the same logical instruction.
       *
       * Only to be called by {@link Assembler#bindLabel(Label)}.
       *
       * @param pos
       *            an instruction's position in the assembler's instruction stream
       *
       * @see Assembler#bindLabel(Label)
       */
      void bind(int pos) {
          this.position = pos;
          state = State.BOUND;
      }
  
      void adjust(int delta) {
          assert state == State.BOUND;
          position += delta;
      }
  
      private int address32;
      private long address64;
  
      /**
       * Assigns a fixed, absolute 32-bit address to this label.
       * If used in a 64-bit assembler,
       * the effective address value would be unsigned-extended.
       *
       * @param address an absolute memory location
       *
       * @see Assembler#bindLabel(Label)
       */
      void fix32(int addr32) {
          this.address32 = addr32;
          state = State.FIXED_32;
      }
  
      /**
       * Assigns a fixed, absolute 64-bit address to this label.
       *
       * @param address an absolute memory location
       *
       * @see Assembler#bindLabel(Label)
       */
      void fix64(long addr64) {
          this.address64 = addr64;
          state = State.FIXED_64;
      }
  
      /**
       * Must only be called if this label has been {@link #fix32 fixed}.
       */
      public int address32() throws AssemblyException {
          switch (state) {
              case FIXED_32: {
                  return address32;
              }
              case FIXED_64: {
                  throw ProgramError.unexpected("64-bit address in 32-bit assembler");
              }
              default: {
                  throw new AssemblyException("unassigned or unfixed label");
              }
          }
      }
  
      /**
       * Must only be called if this label has been {@link #fix64 fixed}.
       */
      public long address64() throws AssemblyException {
          switch (state) {
              case FIXED_64: {
                  return address64;
              }
              case FIXED_32: {
                  throw ProgramError.unexpected("32-bit address in 64-bit assembler");
              }
              default: {
                  throw new AssemblyException("unassigned or unfixed label");
              }
          }
      }
  
      public String externalValue() {
          throw ProgramError.unexpected();
      }
  
      public String disassembledValue() {
          throw ProgramError.unexpected();
      }
  
      public long asLong() {
          throw ProgramError.unexpected("unimplemented");
      }
  
      @Override
      public boolean equals(Object other) {
          if (other instanceof Label) {
              final Label label = (Label) other;
              if (state != label.state) {
                  return false;
              }
              switch (state) {
                  case UNASSIGNED:
                      return this == label;
                  case BOUND:
                      return position == label.position;
                  case FIXED_32:
                      return address32 == label.address32;
                  case FIXED_64:
                      return address64 == label.address64;
                  default:
                      throw ProgramError.unexpected();
              }
          }
          return false;
      }
  
      @Override
      public int hashCode() {
          switch (state) {
              case BOUND:
                  return position;
              case FIXED_32:
                  return address32;
              case FIXED_64:
                  return (int) (address64 ^ (address64 >> 32));
              default:
                  return super.hashCode();
          }
      }
  
      @Override
      public String toString() {
  