total overhaul: fleetcode-1.0 api finished
[fleet.git] / src / edu / berkeley / fleet / ies44 / InstructionEncoder.java
index 7a3d3cd..9173e8c 100644 (file)
@@ -1,85 +1,98 @@
 package edu.berkeley.fleet.ies44;
-import edu.berkeley.fleet.api.*;
-import edu.berkeley.fleet.*;
 import java.io.*;
-import static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.util.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Instruction.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+
 
 public abstract class InstructionEncoder {
 
-    public static final int WIDTH_WORD             = 37;   /* word width */
-    public static final int WIDTH_CODEBAG_SIZE     = 6;
-    public static final int WIDTH_PUMP_ADDR        = 11;
-    public static final int WIDTH_DEST_ADDR        = 11;
-    public static final int WIDTH_COUNT            = 7;
-
-    public static final int OFFSET_MASK_LITERAL    = 24;
-    public static final int WIDTH_MASK_LITERAL     = 2;
-    public static final int MASK_LITERAL           = 1;
-    /*
-    public static final int OFFSET_MASK_LITERAL    = 20;
-    public static final int WIDTH_MASK_LITERAL     = 6;
-    public static final int MASK_LITERAL           = 13;
-    */
-
-    public static final int OFFSET_MASK_MASSACRE   = 14;
-    public static final int WIDTH_MASK_MASSACRE    = 26-14;
-    public static final int MASK_MASSACRE          = 1;
-
-    //public static final int OFFSET_MASK_KILL       = 21;
-    //public static final int WIDTH_MASK_KILL        = 5;
-    //public static final int MASK_KILL              = 5;
-    public static final int OFFSET_MASK_KILL       = 14;
-    public static final int WIDTH_MASK_KILL        = 26-14;
-    public static final int MASK_KILL              = 0;
-
-    //public static final int OFFSET_MASK_UNCLOG     = 21;
-    //public static final int WIDTH_MASK_UNCLOG      = 5;
-    //public static final int MASK_UNCLOG            = 2;
-    public static final int OFFSET_MASK_UNCLOG     = 14;
-    public static final int WIDTH_MASK_UNCLOG      = 26-14;
-    public static final int MASK_UNCLOG            = 3;
-
-    //public static final int OFFSET_MASK_CLOG       = 21;
-    //public static final int WIDTH_MASK_CLOG        = 5;
-    //public static final int MASK_CLOG              = 4;
-    public static final int OFFSET_MASK_CLOG       = 14;
-    public static final int WIDTH_MASK_CLOG        = 26-14;
-    public static final int MASK_CLOG              = 2;
-
-    public static final int OFFSET_MASK_NORMAL     = 25;
-    public static final int WIDTH_MASK_NORMAL      = 1;
-    public static final int MASK_NORMAL            = 1;
-
-    public static final int OFFSET_COUNT           = 0;
-    public static final int OFFSET_DEST            = OFFSET_COUNT+WIDTH_COUNT;
-    public static final int OFFSET_CONTROL         = OFFSET_DEST+WIDTH_DEST_ADDR;
-    public static final int OFFSET_RQ              = OFFSET_CONTROL+0;
-    public static final int OFFSET_IG              = OFFSET_CONTROL+1;
-    public static final int OFFSET_TO              = OFFSET_CONTROL+2;
-    public static final int OFFSET_DO              = OFFSET_CONTROL+3;
-    public static final int OFFSET_DL              = OFFSET_CONTROL+4;
-    public static final int OFFSET_DI              = OFFSET_CONTROL+5;
-    public static final int OFFSET_TI              = OFFSET_CONTROL+6;
-    public static final int OFFSET_INSTRUCTIONTYPE = OFFSET_CONTROL+7;
-    public static final int OFFSET_PUMP_ADDR       = OFFSET_INSTRUCTIONTYPE+1;
-
-    public static final int OFFSET_LITERAL         = OFFSET_COUNT+WIDTH_COUNT;
-    public static final int WIDTH_LITERAL          = OFFSET_MASK_LITERAL - OFFSET_LITERAL;
+    public static final Mask PACKET_TOKEN               = new Mask("v.................................................");
+    public static final Mask PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
+    public static final Mask PACKET_SIGNAL              = new Mask("......................................v...........");
+    public static final Mask PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
+
+    public static final Mask CBD_SIZE                   = new Mask("...............................vvvvvv");
+    public static final Mask CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
+
+    public static final int  WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
+    public static final int  WIDTH_PACKET               = PACKET_TOKEN.width;
+
+    public static final Mask DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
+    public static final Mask I                          = new Mask("...........1.........................");
+    public static final Mask OS                         = new Mask("............1........................");
+    public static final Mask P                          = new Mask(".............vvv.....................");
+    public static final Mask P_NOT_A                    = new Mask(".............000.....................");
+    public static final Mask P_A                        = new Mask(".............001.....................");
+    public static final Mask P_NOT_B                    = new Mask(".............010.....................");
+    public static final Mask P_B                        = new Mask(".............011.....................");
+    public static final Mask P_NOT_C                    = new Mask(".............100.....................");
+    public static final Mask P_C                        = new Mask(".............101.....................");
+    public static final Mask P_OLC                      = new Mask(".............110.....................");
+    public static final Mask P_ALWAYS                   = new Mask(".............111.....................");
+
+    public static final Mask SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
+
+    public static final Mask TAIL                       = new Mask("................11...................");
+
+    public static final Mask MOVE                       = new Mask("................01...................");
+    public static final Mask TI                         = new Mask("..................1..................");
+    public static final Mask DI                         = new Mask("...................1.................");
+    public static final Mask DC                         = new Mask("....................1................");
+    public static final Mask DO                         = new Mask(".....................1...............");
+    public static final Mask TO                         = new Mask("......................1..............");
+    public static final Mask PATH_IMMEDIATE             = new Mask(".......................1vvvvvvvvvvvvv");
+    public static final Mask PATH_DATA                  = new Mask(".......................01............");
+    public static final Mask PATH_NOCHANGE              = new Mask(".......................00............");
+
+    public static final Mask SET                        = new Mask("................10...................");
+
+    public static final Mask SET_OLC_FROM_IMMEDIATE     = new Mask("................1010000100.....vvvvvv");
+    public static final Mask SET_OLC_FROM_DATA_LATCH    = new Mask("................1010000010...........");
+    public static final Mask SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................1010000001...........");
+
+    public static final Mask SET_ILC_FROM_IMMEDIATE     = new Mask("................1001000100.....vvvvvv");
+    public static final Mask SET_ILC_FROM_INFINITY      = new Mask("................1001000010...........");
+    public static final Mask SET_ILC_FROM_DATA_LATCH    = new Mask("................1001000001...........");
+
+    public static final Mask SET_IMMEDIATE                = new Mask("................1000100.vvvvvvvvvvvvv");
+    public static final Mask SET_IMMEDIATE_EXTEND         = new Mask("................1000100v.............");
+
+    public static final Mask SET_FLAGS                  = new Mask("................1000010..............");
+    public static final Mask SET_FLAGS_A                = new Mask("................1000010..vvvvvv......");
+    public static final Mask SET_FLAGS_B                = new Mask("................1000010........vvvvvv");
+    public static final Mask SET_FLAGS_VALUE_A          = new Mask("1.....");
+    public static final Mask SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
+    public static final Mask SET_FLAGS_VALUE_B          = new Mask("..1...");
+    public static final Mask SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
+    public static final Mask SET_FLAGS_VALUE_C          = new Mask("....1.");
+    public static final Mask SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
+
+    public static final Mask SET_TAPL_FROM_IMMEDIATE    = new Mask("................1000001.vvvvvvvvvvvvv");
+
+
+        public static final long DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
+        private static final long mask  = ~(-1L << DataLatch_WIDTH);
+        public static boolean isSmallEnoughToFit(long immediate) {
+            if ((immediate & ~mask) == 0)   return true;
+            if ((immediate |  mask) == -1L) return true;
+            return false;
+        }
 
     /** get the bits describing this box's location on the DESTINATION HORN */
-    protected abstract long getDestAddr(Destination box);
+    protected abstract long getDestAddr(Path box);
 
-    /** get the bits describing this box's location on the INSTRUCTION HORN */
-    protected abstract long getBoxInstAddr(Pump box);
+    /** decode a path, given the starting point and the bits that comprise it */
+    protected abstract Path getPathByAddr(Dock source, long dest);
 
-    /** given an INSTRUCTION HORN address, retrieve the corresponding Pump object */
-    protected abstract Pump getBoxByInstAddr(long dest);
-    
-    /** given a DESTINATION HORN address, retrieve the corresponding Pump object */
-    protected abstract Destination getDestByAddr(long dest);
+    /** FIXME: this is a hack for now */
+    protected abstract Dock getUniversalSource();
 
     /** read a machine-formatted instruction from a file (into a Java object) */
-    public Instruction readInstruction(DataInputStream is) throws IOException {
+    public Instruction readInstruction(Dock dispatchFrom, DataInputStream is) throws IOException {
         long inst = 0;
         try {
             inst = (inst << 8) | (is.readByte() & 0xff);
@@ -88,106 +101,202 @@ public abstract class InstructionEncoder {
             inst = (inst << 8) | (is.readByte() & 0xff);
             inst = (inst << 8) | (is.readByte() & 0xff);
             inst = (inst << 8) | (is.readByte() & 0xff);
-            return readInstruction(inst);
+            return readInstruction(dispatchFrom, inst);
         } catch (EOFException eof) {
             return null;
         }
     }
 
-    public Instruction readInstruction(long inst) {
-        Pump name           = getBoxByInstAddr(getIntField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, inst));
-        if (getIntField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG,inst)==MASK_UNCLOG)
-            return new Instruction.UnClog(name);
-        if (getIntField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG,inst)==MASK_CLOG)
-            return new Instruction.Clog(name);
-        if (getIntField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE,inst)==MASK_MASSACRE)
-            return new Instruction.Massacre(name);
-        int count           = getIntField(                 OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,     inst);
-        if (getIntField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL,inst)==MASK_KILL)
-            return new Instruction.Kill(name, count);
-        Destination dest    = getDestByAddr   (getIntField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,      inst));
-        boolean tokenIn     = getBit(OFFSET_TI, inst);
-        boolean dataIn      = getBit(OFFSET_DI, inst);
-        boolean latch       = getBit(OFFSET_DL, inst);
-        boolean dataOut     = getBit(OFFSET_DO, inst);
-        boolean tokenOut    = getBit(OFFSET_TO, inst);
-        boolean requeue     = getBit(OFFSET_RQ, inst);
-        boolean ignoreUntilLast = getBit(OFFSET_IG, inst);
-        boolean dataOutDest = name.isOutbox() && dataOut && tokenOut;
-        boolean isLiteral   = getIntField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL, inst)==MASK_LITERAL;
-        if (isLiteral)
-            return new Instruction.LocalLiteral(name, getSignedField(OFFSET_LITERAL+WIDTH_LITERAL-1, OFFSET_LITERAL, inst), 0);
-        if (dataOutDest) tokenOut = false;
-        return new Instruction.Move(name,
-                                    dest,
-                                    count,
-                                    tokenIn,
-                                    dataIn,
-                                    latch,
-                                    dataOutDest,
-                                    dataOut,
-                                    tokenOut,
-                                    requeue,
-                                    ignoreUntilLast);
+    public Instruction readInstruction(Dock dispatchFrom, long inst) {
+        Dock dock = getPathByAddr(getUniversalSource(), DISPATCH_PATH.getval(inst)).getDestination().getDock();
+
+        if (TAIL.get(inst))   return new Tail(dock);
+
+        Predicate predicate = Default;
+        if (P_ALWAYS.get(inst)) predicate = IgnoreOLC;
+        if (P_OLC.get(inst))    predicate = Default;
+        if (P_A.get(inst))      predicate = FlagA;
+        if (P_B.get(inst))      predicate = FlagB;
+        if (P_C.get(inst))      predicate = FlagC;
+        if (P_NOT_A.get(inst))  predicate = NotFlagA;
+        if (P_NOT_B.get(inst))  predicate = NotFlagB;
+        if (P_NOT_C.get(inst))  predicate = NotFlagC;
+
+        boolean looping = !OS.get(inst);
+        if (SHIFT.get(inst))                return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getWordWidth()).set(SHIFT.getval(inst)));
+        if (SET_IMMEDIATE.get(inst)) {
+            boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
+            long immediate = SET_IMMEDIATE.getval(inst);
+            if (extend) immediate |= (-1L << DataLatch_WIDTH);
+            return new Set(dock, looping, predicate, SetDest.DataLatch, (immediate));
+        }
+
+        if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
+            return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
+        if (SET_OLC_FROM_IMMEDIATE.get(inst))
+            return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
+        if (SET_ILC_FROM_IMMEDIATE.get(inst))
+            return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
+        if (SET_OLC_FROM_DATA_LATCH.get(inst))
+            return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
+        if (SET_ILC_FROM_DATA_LATCH.get(inst))
+            return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
+        if (SET_ILC_FROM_INFINITY.get(inst))
+            return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
+        if (SET_FLAGS.get(inst)) {
+            long flag_a = SET_FLAGS_A.getval(inst);
+            long flag_b = SET_FLAGS_B.getval(inst);
+            FlagFunction ap = FlagFunction.ZERO;
+            FlagFunction bp = FlagFunction.ZERO;
+            if (SET_FLAGS_VALUE_A    .get(flag_a)) ap = ap.add(FlagA    );
+            if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
+            if (SET_FLAGS_VALUE_B    .get(flag_a)) ap = ap.add(FlagB    );
+            if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
+            if (SET_FLAGS_VALUE_C    .get(flag_a)) ap = ap.add(FlagC    );
+            if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
+            if (SET_FLAGS_VALUE_A    .get(flag_b)) bp = bp.add(FlagA    );
+            if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
+            if (SET_FLAGS_VALUE_B    .get(flag_b)) bp = bp.add(FlagB    );
+            if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
+            if (SET_FLAGS_VALUE_C    .get(flag_b)) bp = bp.add(FlagC    );
+            if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
+            return new Set(dock, looping, predicate, ap, bp);
+        }
+        if (SET_TAPL_FROM_IMMEDIATE.get(inst))
+            return new Set(dock, looping, predicate, SetDest.TAPL, getPathByAddr(dock, SET_TAPL_FROM_IMMEDIATE.getval(inst)));
+        if (MOVE.get(inst))
+            return new Move(dock,
+                            looping,
+                            predicate,
+                            I.get(inst),
+                            getPathByAddr(dock, PATH_IMMEDIATE.getval(inst)),
+                            TI.get(inst),
+                            DI.get(inst),
+                            DC.get(inst),
+                            PATH_DATA.get(inst),
+                            DO.get(inst),
+                            TO.get(inst)
+                            );
+        throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
     }
 
-    public long writeInstruction(Instruction d) {
+    public long writeInstruction(Dock dispatchFrom, Instruction d) {
         long instr = 0;
 
-        if (d.pump != null)
-            instr |= putField(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1, OFFSET_PUMP_ADDR, getBoxInstAddr(d.pump));
+        if (d.dock != null)
+            instr = DISPATCH_PATH.setval(instr, getDestAddr(getUniversalSource().getPath(d.dock.getInstructionDestination(),null)));
 
-        if (d instanceof Instruction.CodeBagDescriptor) {
-            Instruction.CodeBagDescriptor lc = (Instruction.CodeBagDescriptor)d;
-            d = new Instruction.LocalLiteral(lc.pump, ((lc.offset << WIDTH_CODEBAG_SIZE)) | lc.size, 1);
+        boolean dl = false;
+        Instruction pi = d;
+        if (!pi.looping) instr = OS.set(instr);
+        switch(pi.predicate) {
+            case IgnoreOLC:         instr = P_ALWAYS.set(instr); break;
+            case Default: instr = P_OLC.set(instr); break;
+            case FlagA:      instr = P_A.set(instr);      break;
+            case FlagB:      instr = P_B.set(instr);      break;
+            case FlagC:      instr = P_C.set(instr);      break;
+            case NotFlagA:  instr = P_NOT_A.set(instr);      break;
+            case NotFlagB:  instr = P_NOT_B.set(instr);      break;
+            case NotFlagC:  instr = P_NOT_C.set(instr);      break;
         }
 
-        if (d instanceof Instruction.UnClog) {
-            instr |= putField(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1, OFFSET_MASK_UNCLOG,       MASK_UNCLOG);
-
-        } else if (d instanceof Instruction.Kill) {
-            Instruction.Kill k = (Instruction.Kill)d;
-            instr |= putField(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1, OFFSET_MASK_KILL,       MASK_KILL);
-            instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,           k.count-1);
-
-        } else if (d instanceof Instruction.Clog) {
-            instr |= putField(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1, OFFSET_MASK_CLOG,       MASK_CLOG);
-
-        } else if (d instanceof Instruction.Massacre) {
-            instr |= putField(OFFSET_MASK_MASSACRE+WIDTH_MASK_MASSACRE-1, OFFSET_MASK_MASSACRE,       MASK_MASSACRE);
-
-        } else if (d instanceof Instruction.LocalLiteral) {
-            Instruction.LocalLiteral inst = (Instruction.LocalLiteral)d;
-            if (inst.pump != null) {
-                instr |= putField(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1, OFFSET_MASK_LITERAL,    MASK_LITERAL);
-                instr |= putSignedField(OFFSET_LITERAL+WIDTH_LITERAL-1,           OFFSET_LITERAL,         inst.literal);
-                // FIXME remove soon
-                //instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,               OFFSET_COUNT,           inst.count);
-            } else {
-                instr = inst.literal;
+        if (d instanceof Tail) {
+            instr = TAIL.set(instr);
+
+        } else if (d instanceof Shift) {
+            Shift shift = (Shift)d;
+            instr = SHIFT.set(instr);
+            instr = SHIFT.setval(instr, shift.immediate);
+
+        } else if (d instanceof Set) {
+            Set s = (Set)d;
+            switch(s.dest) {
+                case InnerLoopCounter:
+                    switch(s.source) {
+                        case DataLatch:
+                            instr = SET_ILC_FROM_DATA_LATCH.set(instr);
+                            break;
+                        case Immediate:
+                            instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
+                            break;
+                        case Infinity:
+                            instr = SET_ILC_FROM_INFINITY.set(instr);
+                            break;
+                    }
+                    break;
+                case OuterLoopCounter:
+                    switch(s.source) {
+                        case Decrement:
+                            instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
+                            break;
+                        case DataLatch:
+                            instr = SET_OLC_FROM_DATA_LATCH.set(instr);
+                            break;
+                        case Immediate:
+                            instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
+                            break;
+                    }
+                    break;
+                case TAPL: {
+                    instr = SET_TAPL_FROM_IMMEDIATE.set(instr);
+                    instr = SET_TAPL_FROM_IMMEDIATE.setval(instr, getDestAddr(s.path));
+                    break;
+                }
+                case Flags: {
+                    instr = SET_FLAGS.set(instr);
+                    instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
+                    instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
+                    break;
+                }
+                case DataLatch: {
+                    instr = SET_IMMEDIATE.set(instr);
+                    instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
+                    instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
+                    break;
+                }
+            }
+
+        } else if (d instanceof Move) {
+            Move inst = (Move)d;
+            instr  = MOVE.set(instr);
+            if (inst.tokenIn)                    instr = TI.set(instr);
+            if (inst.dataIn)                     instr = DI.set(instr);
+            if (inst.latchData)                  instr = DC.set(instr);
+            if (inst.dataOut)                    instr = DO.set(instr);
+            if (inst.tokenOut)                   instr = TO.set(instr);
+            if (inst.interruptible)              instr = I.set(instr);
+
+            if (inst.latchPath)                  instr = PATH_DATA.set(instr);
+            else {
+                instr  = PATH_IMMEDIATE.set(instr);
+                instr  = PATH_IMMEDIATE.setval(instr, inst.path==null?0:getDestAddr(inst.path));
             }
 
-        } else if (d instanceof Instruction.Move) {
-            Instruction.Move inst = (Instruction.Move)d;
-            instr |= putField(OFFSET_MASK_NORMAL+WIDTH_MASK_NORMAL-1, OFFSET_MASK_NORMAL,       MASK_NORMAL);
-            instr |= putField(OFFSET_DEST+WIDTH_DEST_ADDR-1,      OFFSET_DEST,        inst.dest==null?0:getDestAddr(inst.dest));
-            instr |= putField(OFFSET_COUNT+WIDTH_COUNT-1,         OFFSET_COUNT,       inst.count);
-            instr |= putField(OFFSET_TI,                          OFFSET_TI,          inst.tokenIn?1:0);
-            instr |= putField(OFFSET_DI,                          OFFSET_DI,          inst.dataIn?1:0);
-            instr |= putField(OFFSET_DL,                          OFFSET_DL,          inst.latch?1:0);
-            instr |= putField(OFFSET_DO,                          OFFSET_DO,          (inst.dataOutDest||inst.dataOut)?1:0);
-            instr |= putField(OFFSET_TO,                          OFFSET_TO,          (inst.dataOutDest||inst.tokenOut)?1:0);
-            instr |= putField(OFFSET_RQ,                          OFFSET_RQ,          inst.requeue?1:0);
-            instr |= putField(OFFSET_IG,                          OFFSET_IG,          inst.ignoreUntilLast?1:0);
+        } else {
+            throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
 
         }
         return instr;
     }
 
-    public void writeInstruction(DataOutputStream os, Instruction d) throws IOException {
-        long instr = writeInstruction(d);
+    public void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction d) throws IOException {
+        long instr = writeInstruction(dispatchFrom, d);
         for(int i=5; i>=0; i--)
-            os.write(getIntField(i*8+7, i*8, instr));
-   }
+            os.write(BitManipulations.getIntField(i*8+7, i*8, instr));
+    }
 
-}
\ No newline at end of file
+    private static long flagFunctionToLong(FlagFunction ff) {
+        long ret = 0;
+        for(Predicate p : ff)
+            switch(p) {
+                case FlagA    : ret = SET_FLAGS_VALUE_A    .set(ret); break;
+                case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
+                case FlagB    : ret = SET_FLAGS_VALUE_B    .set(ret); break;
+                case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
+                case FlagC    : ret = SET_FLAGS_VALUE_C    .set(ret); break;
+                case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
+                default: throw new RuntimeException();
+            }
+        return ret;
+    }
+}