/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.vmmagic.unboxed; import org.vmmagic.Unboxed; import org.vmmagic.pragma.RawStorage; import org.vmmagic.unboxed.harness.ArchitecturalWord; /** * (Mistakes in) comments by Robin Garner * @see Address */ @Unboxed @RawStorage(lengthInWords = true, length = 1) public final class Word { final ArchitecturalWord value; Word(ArchitecturalWord value) { this.value = value; } Word(long value) { this(ArchitecturalWord.fromLong(value)); } /** * Convert an into to a word. On 64-bit machines, sign-extend the * high order bit. * * @param val * @return */ public static Word fromIntSignExtend(int val) { return new Word(val); } /** * Convert an int to a word. On 64-bit machines, zero-extend the * high order bit. * * @param val * @return */ @SuppressWarnings("cast") public static Word fromIntZeroExtend(int val) { return new Word(((long)val) & 0xFFFFFFFFL); } /** * Convert a long to a word, truncating to a 32-bit value. * * @param val * @return */ public static Word fromLong(long val) { return new Word(val); } /** * The Word constant 0. * Equivalent to Word.fromIntSignExtend(0), but more readable. * * @return */ public static Word zero() { return new Word(0); } /** * The Word constant 1. * Equivalent to Word.fromIntSignExtend(1), but more readable. * * @return */ public static Word one() { return new Word(1); } /** * The maximum representable Word value. Words are unsigned, so this is * a word full of 1s, 32/64-bit safe. * * @return */ public static Word max() { return new Word(0xFFFFFFFF); } /** * Type-cast to an int, truncating on 64-bit platforms. * * @return */ public int toInt() { return value.toInt(); } /** * Type-cast to a long, zero-extending on a 32-bit platform. * @return */ public long toLong() { return value.toLongZeroExtend(); } /** Type-cast to an address. */ public Address toAddress() { return new Address(value); } /** Type-cast to an offset */ public Offset toOffset() { return new Offset(value); } /** Type-cast to an extent */ public Extent toExtent() { return new Extent(value); } /** * Add two words * * @param w2 * @return */ public Word plus(Word w2) { return new Word(value.plus(w2.toLong())); } /** * Add an offset to a word * @param w2 * @return */ public Word plus(Offset w2) { return new Word(value.plus(w2.toLong())); } /** * Add an extent to a word * @param w2 * @return */ public Word plus(Extent w2) { return new Word(value.plus(w2.toLong())); } /** * Subtract two words * @param w2 * @return */ public Word minus(Word w2) { return new Word(value.minus(w2.toLong())); } /** * Subtract an offset from a word * @param w2 * @return */ public Word minus(Offset w2) { return new Word(value.minus(w2.toLong())); } /** * Subtract an extent from a word. * @param w2 * @return */ public Word minus(Extent w2) { return new Word(value.minus(w2.toLong())); } /** * Test for zero. Equivalent to .EQ(Word.zero()) * @return */ public boolean isZero() { return value.isZero(); } /** * Test for zero. Equivalent to .EQ(Word.max()) * @return */ public boolean isMax() { return value.isMax(); } /** * Less-than comparison * @param addr2 * @return */ public boolean LT(Word w2) { return value.LT(w2.value); } /** * Less-than or equal comparison * @param addr2 * @return */ public boolean LE(Word w2) { return value.LE(w2.value); } /** * Greater-than comparison * @param addr2 * @return */ public boolean GT(Word w2) { return w2.LT(this); } /** * Greater-than or equal comparison * @param addr2 * @return */ public boolean GE(Word w2) { return value.GE(w2.value); } /** * Equality comparison * @param w2 * @return */ public boolean EQ(Word w2) { return value.EQ(w2.value); } /** * Not-equal comparison * @param w2 * @return */ public boolean NE(Word w2) { return value.NE(w2.value); } /** * Bit-wise and of two words. * @param w2 * @return */ public Word and(Word w2) { return new Word(value.and(w2.value)); } /** * Bit-wise or of two words. * @param w2 * @return */ public Word or(Word w2) { return new Word(value.or(w2.value)); } /** * Bit-wise complement of a word. * @param w2 * @return */ public Word not() { return new Word(value.not()); } /** * Bit-wise exclusive or of two words. * @param w2 * @return */ public Word xor(Word w2) { return new Word(value.xor(w2.value)); } /** * Left-shift a word. Shifts of a size greater than the Word are undefined and * have an architecture and compiler specific behaviour. On Intel the shift * amount ignores the most significant bits, for example for a 32bit Word 1 * << 32 == 1, the result will be 0 on PowerPC. Shifts may or may not be * combined by the compiler, this yields differing behaviour, for example for a * 32bit Word 1 <<32 may or may not equal 1 << 16 << 16. * * @param amt the amount to shift by * @return new Word shifted by the given amount */ public Word lsh(int amt) { return new Word(value.lsh(amt)); } /** * Logical right-shift a word. Shifts of a size greater than the Word are undefined and * have an architecture and compiler specific behaviour {@see #lsh(int)}. * * @param amt the amount to shift by * @return new Word shifted by the given amount */ public Word rshl(int amt) { return new Word(value.rshl(amt)); } /** * Arithmetic right-shift a word. Shifts of a size greater than the Word are undefined and * have an architecture and compiler specific behaviour {@see #lsh(int)}. * Arithmetic right-shift a word. Equivalent to the integer <code>>></code> operator * * @param amt the amount to shift by * @return new Word shifted by the given amount */ public Word rsha(int amt) { return new Word(value.rsha(amt)); } /** * The natural string representation of a word, a series of hex digits. */ @Override public String toString() { return value.toString(); } }