/**
* Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codesourcery.jasm16;
/**
* Represents an address (immutable object).
*
* <p>This class provides an abstraction for address values to avoid conversion errors
* when converting byte-sized addresses to/from word-sized addresses or doing address calculations.</p>
*
* <p>Conversion between these types is possible using the {@link #toByteAddress()} and
* {@link #toWordAddress()} methods.
* </p>
*
* @author tobias.gierke@code-sourcery.de
*/
public abstract class Address implements Comparable<Address>
{
public static final WordAddress ZERO = new WordAddress(0);
public static WordAddress wordAddress( long value)
{
if ( value == 0 ) {
return ZERO;
}
return new WordAddress( value );
}
public static ByteAddress byteAddress( long value)
{
if ( value == 0 ) {
return ByteAddress.ZERO;
}
return new ByteAddress( value );
}
@Override
public int compareTo(Address other)
{
final int value1 = this.getByteAddressValue();
final int value2 = other.getByteAddressValue();
if ( value1 < value2 ) {
return -1;
}
if ( value1 > value2 ) {
return 1;
}
return 0;
}
public final boolean isLessThan(Address other)
{
return this.getByteAddressValue() < other.getByteAddressValue();
}
public final boolean isEqualOrLessThan(Address other)
{
return this.getByteAddressValue() <= other.getByteAddressValue();
}
public final boolean isGreaterThan(Address other)
{
return this.getByteAddressValue() > other.getByteAddressValue();
}
public final boolean isEqualOrGreaterThan(Address other)
{
return this.getByteAddressValue() >= other.getByteAddressValue();
}
@Override
public final boolean equals(Object that)
{
if ( that == this ) {
return true;
}
if ( that instanceof Address)
{
return this.getByteAddressValue() == ((Address) that).getByteAddressValue();
}
return false;
}
@Override
public final int hashCode()
{
return getByteAddressValue();
}
/**
* Increments this address by one (with optional wrapping at end of DCPU16 address space).
*
* <p>The DCPU address space is currently 64k words (=128 KB).</p>
* @return
*/
public abstract Address incrementByOne(boolean wrap);
/**
* Decrements this address by one (with optional wrapping at end of DCPU16 address space).
*
* <p>The DCPU address space is currently 64k words (=128 KB).</p>
* @return
*/
public abstract Address decrementByOne();
/**
* Add another address to this one (while wrapping at end of DCPU16 address space).
*
* <p>The DCPU address space is currently 64k words (=128 KB).</p>
* @return
*/
public abstract Address plus(Address other,boolean wrap);
/**
* Subtract another address from this one (while wrapping at start of DCPU16 address space).
*
* <p>The DCPU address space is currently 64k words (=128 KB).</p>
* @return
*/
public abstract Address minus(Address other);
public abstract Address minus(Size size);
public abstract Address plus(Size size,boolean wrap);
/**
* Returns the raw value of this address.
*
* <p>Make sure you know whether this is a word-sized or byte-sized
* address!
* </p>
* @return
*/
public abstract int getValue();
public abstract ByteAddress toByteAddress();
public abstract WordAddress toWordAddress();
public abstract int getByteAddressValue();
public abstract int getWordAddressValue();
public static int alignTo16Bit(int sizeInBytes)
{
int result = sizeInBytes;
while ( (result % 2 ) != 0 ) {
result++;
}
return result;
}
public static Size calcDistanceInBytes(Address start, Address end) {
int startNormalized = start.getByteAddressValue();
int endNormalized = end.getByteAddressValue();
if ( startNormalized <= endNormalized ) {
return Size.bytes( endNormalized - startNormalized );
}
final int len1 = (int) ((ByteAddress.MAX_ADDRESS+1) - startNormalized);
final int len2 = endNormalized;
return Size.bytes( len1+len2 );
}
}