package toy; /** * * @author Brian Tsang * @version 7.0 */ public class ToyWord { public static final ToyWord instances[] = new ToyWord[Short.MAX_VALUE - Short.MIN_VALUE]; public static final ToyWord UNDEFINED = new ToyWord(); //////////////////////////////////////////////////////////////////////////// // Variables private short value; private boolean isDefined; //////////////////////////////////////////////////////////////////////////// // The Constructors private ToyWord() { value = 0; isDefined = false; } public ToyWord(short newValue) { value = newValue; isDefined = true; } //////////////////////////////////////////////////////////////////////////// // isDefined() returns wheter or not this word has been defined yet public boolean isDefined() { return isDefined; } //////////////////////////////////////////////////////////////////////////// // getValue() returns the value of this word public short getValue() { return value; } public static ToyWord parseBinary(boolean newValue[]) { if (newValue != null && newValue.length == 16) { short shortValue = 0; for (int ctr = 15; ctr >= 0; ctr--) { shortValue = (short)(shortValue << 1); if (newValue[ctr]) shortValue |= 1; } return new ToyWord(shortValue); } else return UNDEFINED; } public static ToyWord parseBinary(String newValue) { try { short shortValue = Short.parseShort(newValue, 2); return new ToyWord(shortValue); } catch (Exception e) { return UNDEFINED; } } public static ToyWord parseDecimal(double newValue) { return new ToyWord((short)newValue); } public static ToyWord parseDecimal(String newValue) { try { short shortValue = Short.parseShort(newValue); return new ToyWord(shortValue); } catch (Exception e) { return UNDEFINED; } } public static ToyWord parseHexidecimal(String newValue) { if (newValue != null && newValue.length() == 4) return parseHexidecimal( newValue.charAt(0), newValue.charAt(1), newValue.charAt(2), newValue.charAt(3) ); else return UNDEFINED; } public static ToyWord parseHexidecimal(char op, char rd, char rs, char rt) { if (isHexDigit(op) && isHexDigit(rd) && isHexDigit(rs) && isHexDigit(rt)) { short shortValue; shortValue = convertFromHexDigit(op); shortValue = (short)(shortValue << 4); shortValue |= convertFromHexDigit(rd); shortValue = (short)(shortValue << 4); shortValue |= convertFromHexDigit(rs); shortValue = (short)(shortValue << 4); shortValue |= convertFromHexDigit(rt); return new ToyWord(shortValue); } else return UNDEFINED; } //////////////////////////////////////////////////////////////////////////// // equals() returns wheter or not two ToyWords are equal public boolean equals(Object obj) { if (obj instanceof ToyWord) { return ((ToyWord)obj).isDefined() == isDefined && ((ToyWord)obj).getValue() == value; } else return false; } //////////////////////////////////////////////////////////////////////////// // toBinaryString() returns a string containing the binary representation // of the short. If the user specifies isFormatted as true, the string will // have a space every 4 bits. Example: // "0101 1010 0110 1100" public String toBinaryString() { return toBinaryString(value); } public String toBinaryString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return toBinaryString(value); else return "????????????????"; } public String toFormattedBinaryString() { return toFormattedBinaryString(value); } public String toFormattedBinaryString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return toFormattedBinaryString(value); else return "???? ???? ???? ????"; } //////////////////////////////////////////////////////////////////////////// // toDecimalString() returns the decimal representation of this word public String toDecimalString() { return String.valueOf(value); } public String toDecimalString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return String.valueOf(value); else return ("?????"); } //////////////////////////////////////////////////////////////////////////// // toHexString() returns the hexidecimal representation of this word public String toHexString() { return toHexString(value); } public String toHexString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return toHexString(value); else return "????"; } //////////////////////////////////////////////////////////////////////////// // toString() returns a string containing all the numerical representations // of this word public String toString() { return toString(value); } public String toString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return toString(value); else return "Uninitialized Memory Location"; } //////////////////////////////////////////////////////////////////////////// // toPseudoCodeString() returns a string representing this the pseudocode // equivalent of this word (assuming it's a command) public String toPseudoCodeString() { return toPseudoCodeString(value); } public String toPseudoCodeString(boolean uninitializedErrorEnabled) { if (isDefined || !uninitializedErrorEnabled) return toPseudoCodeString(value); else return "Uninitialized Memory Location"; } //////////////////////////////////////////////////////////////////////////// // toBinaryString() returns a string containing the binary representation // of the short. If the user specifies isFormatted as true, the string will // have a space every 4 bits. Example: // "0101 1010 0110 1100" public static String toBinaryString(short newValue) { String answer = ""; for (int ctr = 0; ctr < 16; ctr++) { if (((newValue >> ctr) & 1) == 1) answer = "1" + answer; else answer = "0" + answer; } return answer; } public static String toFormattedBinaryString(short newValue) { String answer = ""; for (int ctr1 = 0; ctr1 < 4; ctr1++) { for (int ctr2 = 0; ctr2 < 4; ctr2++) { if (((newValue >> (ctr1 * 4 + ctr2)) & 1) == 1) answer = "1" + answer; else answer = "0" + answer; } if (ctr1 != 3) answer = " " + answer; } return answer; } //////////////////////////////////////////////////////////////////////////// // toHexString() returns the hexidecimal representation of this word public static String toHexString(short newValue) { String answer = ""; answer += convertToHexDigit((short)((newValue & 0xF000) >> 12)); answer += convertToHexDigit((short)((newValue & 0x0F00) >> 8)); answer += convertToHexDigit((short)((newValue & 0x00F0) >> 4)); answer += convertToHexDigit((short) (newValue & 0x000F)); return answer; } //////////////////////////////////////////////////////////////////////////// // toString() returns a string containing all the numerical representations // of this word public static String toString(short newValue) { return "(" + toFormattedBinaryString(newValue) + ", " + newValue + ")"; } //////////////////////////////////////////////////////////////////////////// // toPseudoCodeString() returns a string representing this the pseudocode // equivalent of this word (assuming it's a command) public static String toPseudoCodeString(short newValue) { char op, rd, rs, rt; op = convertToHexDigit((short)((newValue & 0xF000) >> 12)); rd = convertToHexDigit((short)((newValue & 0x0F00) >> 8)); rs = convertToHexDigit((short)((newValue & 0x00F0) >> 4)); rt = convertToHexDigit((short) (newValue & 0x000F)); switch (op) { case '0': return "halt"; case '1': if (rs == '0' && rt != '0') return "R[" + rd + "] <- R[" + rt + "]"; if (rs != '0' && rt == '0') return "R[" + rd + "] <- R[" + rs + "]"; if (rs == '0' && rt == '0') return "no-op"; return "R[" + rd + "] <- R[" + rs + "] + R[" + rt + "]"; case '2': if (rs == '0' && rt != '0') return "R[" + rd + "] <- -R[" + rt + "]"; if (rs != '0' && rt == '0') return "R[" + rd + "] <- R[" + rs + "]"; if (rs == '0' && rt == '0') return "R[" + rd + "] <- 0000"; return "R[" + rd + "] <- R[" + rs + "] - R[" + rt + "]"; case '3': if (rs == '0' || rt == '0') return "R[" + rd + "] <- 0000"; if (rs == rt) return "R[" + rd + "] <- R[" + rs + "]"; return "R[" + rd + "] <- R[" + rs + "] & R[" + rt + "]"; case '4': if (rs == '0' && rt != '0') return "R[" + rd + "] <- R[" + rt + "]"; if (rs != '0' && rt == '0') return "R[" + rd + "] <- R[" + rs + "]"; if (rs == '0' && rt == '0') return "R[" + rd + "] <- 0000"; return "R[" + rd + "] <- R[" + rs + "] ^ R[" + rt + "]"; case '5': if (rs == '0') return "R[" + rd + "] <- 0000"; if (rt == '0') return "R[" + rd + "] <- R[" + rs + "]"; return "R[" + rd + "] <- R[" + rs + "] << R[" + rt + "]"; case '6': if (rs == '0') return "R[" + rd + "] <- 0000"; if (rt == '0') return "R[" + rd + "] <- R[" + rs + "]"; return "R[" + rd + "] <- R[" + rs + "] >> R[" + rt + "]"; case '7': return "R[" + rd + "] <- 00" + rs + rt; case '8': if (rs == 'F' && rt == 'F') return "read R[" + rd + "]"; else return "R[" + rd + "] <- mem[" + rs + rt + "]"; case '9': if (rs == 'F' && rt == 'F') return "write R[" + rd + "]"; else return "mem[" + rs + rt + "] <- R[" + rd + "]"; case 'A': return "R[" + rd + "] <- mem[R[" + rt + "]]"; case 'B': return "mem[R[" + rt + "]] <- R[" + rd + "]"; case 'C': if (rd == '0') return "goto " + rs + rt; return "if (R[" + rd + "] == 0) goto " + rs + rt; case 'D': return "if (R[" + rd + "] > 0) goto " + rs + rt; case 'E': return "goto R[" + rd + "]"; case 'F': return "R[" + rd + "] <- pc; goto " + rs + rt; } return ""; } //////////////////////////////////////////////////////////////////////////// // add() is a static function that adds two ToyWords together and returns // a new ToyWord containing the sum (it can throw an overflow or // uninitialized ToyException if the user permits them) public static ToyWord add(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled, boolean overflowErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); //we add the values as ints so we can check for overflow long sum = a.getValue() + b.getValue(); if ((sum < Short.MIN_VALUE || sum > Short.MAX_VALUE) && overflowErrorEnabled) throw new ToyException(ToyException.OVERFLOW); return new ToyWord((short)sum); } //////////////////////////////////////////////////////////////////////////// // subtract() is a static function that subtracts two ToyWords from each // other and returns a new ToyWord containing the difference (it can throw // an overflow or uninitialized ToyException if the user permits them) public static ToyWord subtract(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled, boolean overflowErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); //we subtract the values as ints so we can check for overflow long difference = a.getValue() - b.getValue(); if ((difference < Short.MIN_VALUE || difference > Short.MAX_VALUE) && overflowErrorEnabled) throw new ToyException(ToyException.OVERFLOW); return new ToyWord((short)difference); } //////////////////////////////////////////////////////////////////////////// // and() is a static function that and's two ToyWords and returns a new // ToyWord containing the result (it can throw an uninitialized // ToyException if the user permits it) public static ToyWord and(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); return new ToyWord((short)(a.getValue() & b.getValue())); } //////////////////////////////////////////////////////////////////////////// // xor() is a static function that xor's two ToyWords and returns a new // ToyWord containing the result (it can throw an uninitialized // ToyException if the user permits it) public static ToyWord xor(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); return new ToyWord((short)(a.getValue() ^ b.getValue())); } //////////////////////////////////////////////////////////////////////////// // leftShift() is a static function that takes one ToyWord and a short and // returns a ToyWord containg the left-shifted value (it can throw an // uninitialized ToyException if the user permits it) public static ToyWord leftShift(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled, boolean overflowErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); if ((b.getValue() & 0xF) != b.getValue()) throw new ToyException(ToyException.SHIFT_OUT_OF_BOUNDS); return new ToyWord((short)(a.getValue() << (b.getValue() & 0xF))); } //////////////////////////////////////////////////////////////////////////// // rightShift() is a static function that takes one ToyWord and a short and // returns a ToyWord containg the right-shifted value (it can throw an // uninitialized ToyException if the user permits it) public static ToyWord rightShift(ToyWord a, ToyWord b, boolean uninitializedErrorEnabled, boolean overflowErrorEnabled) throws ToyException { if ((!a.isDefined() || !b.isDefined()) && uninitializedErrorEnabled) throw new ToyException(ToyException.VARIABLE_UNINITIALIZED); if ((b.getValue() & 0xF) != b.getValue()) throw new ToyException(ToyException.SHIFT_OUT_OF_BOUNDS); return new ToyWord((short)(a.getValue() >>> (b.getValue() & 0xF))); } //////////////////////////////////////////////////////////////////////////// // isHexDigit() is a test to see whether or not a character is a hexidecimal // digit public static boolean isHexDigit(char c) { return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'; } //////////////////////////////////////////////////////////////////////////// // convertFromHexDigit() returns a short containing the value of a char // in base 16 public static short convertFromHexDigit(char c) { if (c >= '0' && c <= '9') return (short)(c - '0'); if (c >= 'A' && c <= 'F') return (short)(c - 'A' + 10); if (c >= 'a' && c <= 'f') return (short)(c - 'a' + 10); return -1; } //////////////////////////////////////////////////////////////////////////// // convertFromHexDigit() returns a char corresponding to the base 16 // representation of a short public static char convertToHexDigit(short value) { if (value >= 0 && value <= 9) return (char)(value + '0'); if (value >= 10 && value <= 16) return (char)(value + 'A' - 10); return '?'; } }