view graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/risc/bitRange/BitRange.java @ 4142:bc8527f3071c

Adjust code base to new level of warnings.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 18 Dec 2011 05:24:06 +0100
parents e233f5660da4
children
line wrap: on
line source

/*
 * 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.gen.risc.bitRange;

/**
 * A {@code BitRange} is a specification of how a field's value is encoded in the
 * bit positions in an instruction. The bit positions are not necessarily contiguous.
 * In addition, one or more implicit bits for a field's value can be specified with an
 * {@link OmittedBitRange}.
 */
public abstract class BitRange {

    /**
     * Creates a bit range from {@code bits}, a series of from-to pairs (inclusive) or negative numbers.
     * For example, if {@code bits} is the integer array {@code {2, 4, 30, 31, -2, 18, 18}} then
     * the field encodes an 8 bit value where bits 7:5 of the value are encoded in bit positions
     * 2:4 of the instruction, bits 4:3 of the value are encoded in bit positions 30:31 of the instruction,
     * bits 2:1 of the value are both 0 and bit 0 of the value is encoded in bit position 18 of the instruction.
     * This bitrange has a {@link #width width} of 8 and an {@link #encodedWidth encoded width} of 6.
     *
     * @param bits   the bit range specification
     * @param order  how contiguous bit ranges are specified in the relevant architecture manual
     */
    public static BitRange create(int[] bits, BitRangeOrder order) {
        if (bits.length == 2) {
            final int first = bits[0];
            final int last = bits[1];
            return order.createSimpleBitRange(first, last);
        } else if (bits.length > 2) {
            final CompoundBitRange compoundBitRange = new CompoundBitRange();
            int i = 0;
            while (i < bits.length) {
                final int first = bits[i];
                i++;
                if (first >= 0) {
                    final int last = bits[i];
                    i++;
                    compoundBitRange.add(order.createSimpleBitRange(first, last));
                } else {
                    compoundBitRange.add(new OmittedBitRange(-first));
                }
            }
            return compoundBitRange;
        } else if (bits.length == 1) {
            final int omittedWidth = bits[0];
            if (omittedWidth < 0) {
                return new OmittedBitRange(-omittedWidth);
            }
            // else this is an error; fall through
        }
        throw new IllegalArgumentException("invalid bit range");
    }

    /**
     * @return the number of bits required to represent the range of values represented by the
     *         field associated with this bit range
     */
    public abstract int width();

    /**
     * @return the number of bits required to encode the range of values represented by the
     *         field associated with this bit range (which may be less than {@link #width}
     *         if the range includes an {@link OmittedBitRange})
     */
    public abstract int encodedWidth();

    /**
     * @return the number of bits that would be less significant than those specified by this bit range
     */
    public abstract int numberOfLessSignificantBits();

    /*
     * @return a mask that expresses this bit range's mere width, indicating a value range for operands
     */
    public int valueMask() {
        final int width = width();
        if (width == 32) {
            return ~0;
        }
        return (1 << width) - 1;
    }

    /**
     * @return a mask with the bits of this range set to 1 in the actually addressed bit positions
     */
    public abstract int instructionMask();

    @Override
    public abstract boolean equals(Object other);

    @Override
    public abstract int hashCode();

    public abstract int extractSignedInt(int instruction);

    public abstract int extractUnsignedInt(int instruction);

    public abstract int assembleUncheckedSignedInt(int signedInt);

    public abstract int assembleUncheckedUnsignedInt(int unsignedInt);

    /**
     * Gets the Java source code to encode {@code value} into the field represented by this bit range.
     *
     * @param value    the value to be encoded
     * @param signed   specifies if the value is signed
     * @param checked  specifies if {@code value} is guaranteed to be within the valid range of values for this bit range
     *                 (and therefore does not require masking)
     * @return the Java source code to encode {@code value} into the field represented by this bit range
     */
    public abstract String encodingString(String value, boolean signed, boolean checked);

    public abstract BitRange move(boolean left, int bits);

    protected void checkRangeOfSignedInt(int signedInt) throws IllegalArgumentException {
        final int width = width();
        final int mostNegative = -1 << (width - 1);
        final int tooPositive = 1 << (width - 1);

        if (signedInt < mostNegative) {
            throw new IllegalArgumentException(Integer.toHexString(signedInt) + " < " + Integer.toHexString(mostNegative) + " and so is too negative to fit in a signed " + width + "-bit bit-range");
        }
        if (signedInt >= tooPositive) {
            throw new IllegalArgumentException(Integer.toHexString(signedInt) + " >= " + Integer.toHexString(tooPositive) + " and so is too positive to fit in a signed " + width + "-bit bit-range");
        }
    }

    protected void checkRangeOfUnsignedInt(int unsignedInt) throws IllegalArgumentException {
        if (width() < 32 && unsignedInt < 0) {
            throw new IllegalArgumentException(Integer.toHexString(unsignedInt) + " is negative and so cannot fit in an unsigned " + width() + "-bit bit-range");
        }
        if (unsignedInt <= valueMask()) {
            return;
        }
        throw new IllegalArgumentException(Integer.toHexString(unsignedInt) + " > " + Integer.toHexString(valueMask()) + " and so is too positive to fit in an unsigned " + width() + "-bit bit-range");
    }

    public int assembleSignedInt(int signedInt) throws IllegalArgumentException {
        checkRangeOfSignedInt(signedInt);
        return assembleUncheckedSignedInt(signedInt);
    }

    public int assembleUnsignedInt(int unsignedInt) throws IllegalArgumentException {
        checkRangeOfUnsignedInt(unsignedInt);
        return assembleUncheckedUnsignedInt(unsignedInt);
    }

}