IES44: lots of cleanup, use safer bitfield operations
authoradam <adam@megacz.com>
Thu, 22 Feb 2007 15:30:50 +0000 (16:30 +0100)
committeradam <adam@megacz.com>
Thu, 22 Feb 2007 15:30:50 +0000 (16:30 +0100)
src/edu/berkeley/fleet/ies44/InstructionEncoder.java

index 0e9174d..c96f6d1 100644 (file)
@@ -6,16 +6,16 @@ import java.io.*;
 public abstract class InstructionEncoder {
 
     /** get the bits describing this box's location on the DESTINATION HORN */
-    public abstract long getBoxAddr(Destination box);
+    protected abstract long getDestAddr(Destination box);
 
     /** get the bits describing this box's location on the INSTRUCTION HORN */
-    public abstract long getBoxInstAddr(BenkoBox box);
-
-    /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
-    public abstract BenkoBox getBoxByAddr(long dest);
+    protected abstract long getBoxInstAddr(BenkoBox box);
 
     /** given an INSTRUCTION HORN address, retrieve the corresponding BenkoBox object */
-    public abstract BenkoBox getBoxByInstAddr(long dest);
+    protected abstract BenkoBox getBoxByInstAddr(long dest);
+    
+    /** given a DESTINATION HORN address, retrieve the corresponding BenkoBox object */
+    protected abstract Destination getDestByAddr(long dest);
 
     /** read a machine-formatted instruction from a file (into a Java object) */
     public Instruction readInstruction(DataInputStream is) throws IOException {
@@ -33,45 +33,90 @@ public abstract class InstructionEncoder {
         }
     }
 
+    // FIXME: use this more
+    private boolean getBit(int bit, long val) { return ((val & (1L << bit)) != 0); }
+    private long getSignedField(int highBit, int lowBit, long val) {
+        long ret = getField(highBit, lowBit, val);
+        if ((ret & (1L << ((highBit-lowBit)+1-1))) != 0)
+            ret |= 0xffffffffffffffffL << ((highBit-lowBit)+1);
+        return ret;
+    }
+    private int getIntField(int highBit, int lowBit, long val) {
+        if (highBit-lowBit+1 > 32) throw new RuntimeException("too big!");
+        return (int)getField(highBit, lowBit, val);
+    }
+    private long getField(int highBit, int lowBit, long val) {
+        long mask = 0xffffffffffffffffL;
+        mask = mask << ((highBit-lowBit)+1);
+        mask = ~mask;
+        mask = mask << lowBit;
+        long ret = val & mask;
+        ret = ret >> lowBit;
+        return ret;
+    }
+
+    private long doPutField(int highBit, int lowBit, long val) {
+        long mask = 0xffffffffffffffffL;
+        mask = mask << (highBit-lowBit+1);
+        mask = ~mask;
+        val = val & mask;
+        val = val << lowBit;
+        return val;
+    }
+    private long putField(int highBit, int lowBit, long val) {
+        if (val < 0 || val >= (1L << (highBit-lowBit+1)))
+            throw new RuntimeException("bitfield width exceeded");
+        return doPutField(highBit, lowBit, val);
+    }
+    private long putSignedField(int highBit, int lowBit, long val) {
+        if (val <= (-1L * (1L << (highBit-lowBit+1-1))))
+            throw new RuntimeException("bitfield width exceeded");
+        if (val >= (      (1L << (highBit-lowBit+1-1))))
+            throw new RuntimeException("bitfield width exceeded");
+        return doPutField(highBit, lowBit, val);
+    }
+
+    // FIXME: parameterize stuff in this file
+    private static final int WBITS              = 37;   /* word width */
+    private static final int IBITS              = 37;   /* instruction width */
+    private static final int CODEBAG_SIZE_BITS  = 6;
+    private static final int BENKOBOX_NAME_BITS = 11;
+    private static final int COUNT_BITS         = 7;
+    private static final int OPCODE_BITS        = 5;
+
     public Instruction readInstruction(long instr) {
         long inst = instr;
-        long head = inst & (0x3L << (24+11));
-        head = head >> (24+11);
-        switch((int)head) {
+        switch((int)getField(WBITS-1, WBITS-2, inst)) {
             case 0: {
-                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
-                BenkoBox dest = getBoxByAddr    ((inst >>  1) & 0x7ff);
-                int count        = ((int)(instr >> 12)) & 0x7f;
-                boolean tokenIn  = (instr & (1L << (11+1+7+0))) != 0;
-                boolean dataIn   = ( instr & (1L << (11+1+7+1))) != 0;
-                boolean latch    = (  instr & (1L << (11+1+7+2))) != 0;
-                boolean dataOut  = (instr & (1L << (11+1+7+3))) != 0;
-                boolean tokenOut = (instr & (1L << (11+1+7+4))) != 0;
-                boolean recycle  = (instr & (1L)) != 0;
+                BenkoBox name    = getBoxByInstAddr((inst >> 24) & 0x7ff);
+                Destination dest = getDestByAddr    ((inst >>  1) & 0x7ff);
+                int count        = getIntField(COUNT_BITS+BENKOBOX_NAME_BITS+1-1, BENKOBOX_NAME_BITS+1, instr);
+                boolean tokenIn  = getBit(COUNT_BITS+BENKOBOX_NAME_BITS+1+0, instr);
+                boolean dataIn   = getBit(COUNT_BITS+BENKOBOX_NAME_BITS+1+1, instr);
+                boolean latch    = getBit(COUNT_BITS+BENKOBOX_NAME_BITS+1+2, instr);
+                boolean dataOut  = getBit(COUNT_BITS+BENKOBOX_NAME_BITS+1+3, instr);
+                boolean tokenOut = getBit(COUNT_BITS+BENKOBOX_NAME_BITS+1+4, instr);
+                boolean recycle  = getBit(0, instr);
                 if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
                 return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
                                                   latch, dataOut, tokenOut, recycle);
             }
 
             case 1: {
-                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
-                int offset = ((int)(instr >> 6)) & ~(0xffffffff << 18);
-                if ((offset & (1<<17)) != 0) offset |= (0xffffffff << 18);
-                int size   = ((int)(instr     )) & ~(0xffffffff << 6);
+                Destination name = getDestByAddr(getField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, inst));
+                long offset = getSignedField(WBITS-3-BENKOBOX_NAME_BITS, CODEBAG_SIZE_BITS, instr);
+                long size   = getSignedField(CODEBAG_SIZE_BITS-1,        0,                 instr);
                 return new Instruction.Literal.CodeBagDescriptor(name, offset, size);
             }
 
             case 2: {
-                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
-                int val   = ((int)(instr     )) & ~(0xffffffff << 24);
-                val = signExtend24(val);
-                return new Instruction.Literal.Absolute(name, val);
+                Destination name = getDestByAddr(getField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, inst));
+                return new Instruction.Literal.Absolute(name, getSignedField(WBITS-3-BENKOBOX_NAME_BITS, 0, instr));
             }
 
             case 3: {
-                BenkoBox name = getBoxByInstAddr((inst >> 24) & 0x7ff);
-                int val   = ((int)(instr     )) & ~(0xffffffff << 24);
-                return new Instruction.Literal.Relative(name, val);
+                Destination name = getDestByAddr(getField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, inst));
+                return new Instruction.Literal.Relative(name, getSignedField(WBITS-3-BENKOBOX_NAME_BITS, 0, instr));
             }
 
         }
@@ -91,48 +136,37 @@ public abstract class InstructionEncoder {
 
         if (d instanceof Instruction.Executable) {
             Instruction.Executable inst = (Instruction.Executable)d;
-            Destination dest = inst.dest;
-            instr = dest==null ? 0 : (getBoxAddr(dest) << 1);
-            if (inst.count >= (1<<8))
-                throw new RuntimeException("count field must be less than 128");
-            instr |= (((long)inst.count) << (11+1));
-            if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
-            if (inst.dataIn)   instr |= (1L << (11+1+7+1));
-            if (inst.latch)    instr |= (1L << (11+1+7+2));
-            if (inst.dataOut)  instr |= (1L << (11+1+7+3));
-            if (inst.tokenOut) instr |= (1L << (11+1+7+4));
-            if (inst.recycle)  instr |= (1L);
-            instr |= (getBoxInstAddr(inst.benkoBox) << (11+5+7+1));
+            if (inst.dest != null)
+                instr |= putField(BENKOBOX_NAME_BITS, 1, getDestAddr(inst.dest));
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1-1, BENKOBOX_NAME_BITS+1,              inst.count);
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1+0, COUNT_BITS+BENKOBOX_NAME_BITS+1+0, inst.tokenIn  ? 1 : 0);
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1+1, COUNT_BITS+BENKOBOX_NAME_BITS+1+1, inst.dataIn   ? 1 : 0);
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1+2, COUNT_BITS+BENKOBOX_NAME_BITS+1+2, inst.latch    ? 1 : 0);
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1+3, COUNT_BITS+BENKOBOX_NAME_BITS+1+3, inst.dataOut  ? 1 : 0);
+            instr |= putField(COUNT_BITS+BENKOBOX_NAME_BITS+1+4, COUNT_BITS+BENKOBOX_NAME_BITS+1+4, inst.tokenOut ? 1 : 0);
+            instr |= putField(0,                                 0,                                 inst.recycle  ? 1 : 0);
+            instr |= putField(BENKOBOX_NAME_BITS+OPCODE_BITS+COUNT_BITS+BENKOBOX_NAME_BITS+1-1,
+                              OPCODE_BITS+COUNT_BITS+BENKOBOX_NAME_BITS+1,
+                              getBoxInstAddr(inst.benkoBox));
 
         } else if (d instanceof Instruction.Literal.CodeBagDescriptor) {
             Instruction.Literal.CodeBagDescriptor lc = (Instruction.Literal.CodeBagDescriptor)d;
-            instr = (1L << (11+24));
-            if (lc.dest != null)
-                instr |= (getBoxAddr(lc.dest)) << 24;
-            if (lc.size >= (1<<6))
-                throw new RuntimeException("codebag sizes must be less than 2^6");
-            if (lc.offset >= (1<<17) || lc.offset <= (-1 * (1<<17)))
-                throw new RuntimeException("codebag offsets must be in the range -(2^17)..2^17");
-            int off = (int)lc.offset;
-            off &= ~(0xffffffff << 18);
-            instr |= (off << 6);
-            instr |= (((long)lc.size));
+            instr = putField(WBITS-1, WBITS-2, 1);
+            if (lc.dest != null) instr |= putField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, getDestAddr(lc.dest));
+            instr |= putSignedField(WBITS-3-BENKOBOX_NAME_BITS, CODEBAG_SIZE_BITS, lc.offset);
+            instr |= putField(CODEBAG_SIZE_BITS-1,        0,                 lc.size);
 
         } else if (d instanceof Instruction.Literal.Absolute) {
             Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
-            instr = (2L << (11+24));
-            instr |= (getBoxAddr(ld.dest)) << 24;
-            if (ld.value >= (1<<25))
-                throw new RuntimeException("literals must be less than 2^24");
-            instr |= ((long)ld.value) & ~(0xffffffff << 24);
+            instr = putField(WBITS-1, WBITS-2, 2);
+            instr |= putField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, getDestAddr(ld.dest));
+            instr |= putSignedField(WBITS-3-BENKOBOX_NAME_BITS, 0, ld.value);
 
         } else if (d instanceof Instruction.Literal.Relative) {
             Instruction.Literal.Relative lr = (Instruction.Literal.Relative)d;
-            instr = (3L << (11+24));
-            instr |= (getBoxAddr(lr.dest)) << 24;
-            if (lr.offset >= (1<<25))
-                throw new RuntimeException("literals must be less than 2^24");
-            instr |= ((long)lr.offset);
+            instr = putField(WBITS-1, WBITS-2, 3);
+            instr |= putField(WBITS-3, WBITS-3-BENKOBOX_NAME_BITS+1, getDestAddr(lr.dest));
+            instr |= putSignedField(WBITS-3-BENKOBOX_NAME_BITS, 0, lr.offset);
             
         }
         return instr;
@@ -140,18 +174,8 @@ public abstract class InstructionEncoder {
 
     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
         long instr = writeInstruction(d);
-        os.write((int)((instr >> (5*8)) & 0xff));
-        os.write((int)((instr >> (4*8)) & 0xff));
-        os.write((int)((instr >> (3*8)) & 0xff));
-        os.write((int)((instr >> (2*8)) & 0xff));
-        os.write((int)((instr >> (1*8)) & 0xff));
-        os.write((int)((instr >> (0*8)) & 0xff));
+        for(int i=5; i>=0; i--)
+            os.write(getIntField(i*8+7, i*8, instr));
    }
 
-    public static int signExtend24(int val) {
-        if ((val & (1 << 23)) != 0)
-            val = val | (0xffffffff << 24);
-        return val;
-    }
-
 }
\ No newline at end of file