add SetFlags instruction to API and interpreter
authoradam <adam@megacz.com>
Mon, 11 Feb 2008 13:08:03 +0000 (14:08 +0100)
committeradam <adam@megacz.com>
Mon, 11 Feb 2008 13:08:03 +0000 (14:08 +0100)
src/edu/berkeley/fleet/api/Instruction.java
src/edu/berkeley/fleet/assembler/Parser.java
src/edu/berkeley/fleet/assembler/fleet.g
src/edu/berkeley/fleet/ies44/InstructionEncoder.java
src/edu/berkeley/fleet/interpreter/InstructionPump.java

index 4cfe0b2..039021e 100644 (file)
@@ -32,6 +32,47 @@ public abstract class Instruction {
         public String toString() { return super.toString() + "kill"+(count==1?"":(" "+count))+";"; }
     }
 
+    public static class SetFlags extends Instruction {
+        public static final int FLAG_Z     = 0x0001;
+        public static final int FLAG_NOT_Z = 0x0002;
+        public static final int FLAG_S     = 0x0004;
+        public static final int FLAG_NOT_S = 0x0008;
+        public static final int FLAG_B     = 0x0010;
+        public static final int FLAG_NOT_B = 0x0020;
+        public static final int FLAG_A     = 0x0040;
+        public static final int FLAG_NOT_A = 0x0080;
+
+        public final int flag_a;
+        public final int flag_b;
+        public SetFlags(Pump pump, int flag_a, int flag_b) {
+            super(pump);
+            this.flag_a = flag_a;
+            this.flag_b = flag_b;
+        }
+
+        public boolean isLooping() { return true; }
+        private String printFlag(int flag) {
+            if (flag==0) return "0";
+            if ((flag & (FLAG_Z | FLAG_NOT_Z)) == (FLAG_Z | FLAG_NOT_Z)) return "1";
+            if ((flag & (FLAG_B | FLAG_NOT_B)) == (FLAG_B | FLAG_NOT_B)) return "1";
+            if ((flag & (FLAG_A | FLAG_NOT_A)) == (FLAG_A | FLAG_NOT_A)) return "1";
+            if ((flag & (FLAG_S | FLAG_NOT_S)) == (FLAG_S | FLAG_NOT_S)) return "1";
+            String ret = "";
+            if ((flag & FLAG_A)     != 0) ret += (ret.length()>=0?"|":"") +  "a";
+            if ((flag & FLAG_NOT_A) != 0) ret += (ret.length()>=0?"|":"") + "!a";
+            if ((flag & FLAG_B)     != 0) ret += (ret.length()>=0?"|":"") +  "b";
+            if ((flag & FLAG_NOT_B) != 0) ret += (ret.length()>=0?"|":"") + "!b";
+            if ((flag & FLAG_S)     != 0) ret += (ret.length()>=0?"|":"") +  "s";
+            if ((flag & FLAG_NOT_S) != 0) ret += (ret.length()>=0?"|":"") + "!s";
+            if ((flag & FLAG_Z)     != 0) ret += (ret.length()>=0?"|":"") +  "z";
+            if ((flag & FLAG_NOT_Z) != 0) ret += (ret.length()>=0?"|":"") + "!z";
+            return ret;
+        }
+        public String toString() {
+            return super.toString() + " setflags a=" + printFlag(flag_a) + ", b=" + printFlag(flag_b);
+        }
+    }
+
     public static class DecrLoop extends Instruction {
         public DecrLoop(Pump pump) { super(pump); }
         public boolean isDL() { return true; }
index dcd5289..05c5aaa 100644 (file)
@@ -6,6 +6,7 @@ import edu.berkeley.sbp.misc.*;
 import edu.berkeley.sbp.meta.*;
 import edu.berkeley.sbp.util.*;
 import static edu.berkeley.fleet.util.BitManipulations.*;
+import static edu.berkeley.fleet.api.Instruction.SetFlags.*;
 import java.util.*;
 import java.io.*;
 
@@ -243,6 +244,24 @@ public class Parser {
         return literal;
     }
 
+    private static int parseFlags(Tree<String> t) {
+        int ret = 0;
+        for(int i=0; i<t.size(); i++) {
+            String s = t.child(i).head();
+            if (s.equals("0")) continue;
+            if (s.equals("1")) { ret |= (FLAG_A | FLAG_NOT_A); }
+            if (s.equals("a"))  ret |= FLAG_A;
+            if (s.equals("!a")) ret |= FLAG_NOT_A;
+            if (s.equals("b"))  ret |= FLAG_B;
+            if (s.equals("!b")) ret |= FLAG_NOT_B;
+            if (s.equals("z"))  ret |= FLAG_Z;
+            if (s.equals("!z")) ret |= FLAG_NOT_Z;
+            if (s.equals("s"))  ret |= FLAG_S;
+            if (s.equals("!s")) ret |= FLAG_NOT_S;
+        }
+        return ret;
+    }
+
     private int anoncount = 1;
     void fillCodeBag(Tree<String> t, CodeBag cb) {
         if (t.head()==null) return;
@@ -266,6 +285,9 @@ public class Parser {
                     count = tt.size()==0 ? 1 : (int)number(tt.child(0));
                     cb.add(new Instruction.Kill(pump, count));
                     continue;
+                } else if ("setflags".equals(tt.head()))    {
+                    cb.add(new Instruction.SetFlags(pump, parseFlags(tt.child(0)), parseFlags(tt.child(1))));
+                    continue;
                 } else if ("loop".equals(tt.head()))    {
                     cb.add(new Instruction.Counter(pump, Instruction.Counter.LOOP_COUNTER, Instruction.Counter.DATA_LATCH));
                     continue;
index 0c89dea..bfe6a3b 100644 (file)
@@ -20,7 +20,7 @@ Instruction     = ^"unclog"                          ";" /ws
                 | ^"load" (^"loop"|^"repeat") ws "counter"             ";" /ws
                 |  "load" (^"loop"|^"repeat") ws "counter" ^"with" int ";" /ws
                 | ^"decrement" "loop" "counter"                        ";" /ws
-                | ^"setflags" ws "a=" Flag ws "b=" Flag ws ";"
+                | ^"setflags" "a" "=" Flags "," "b" "=" Flags          ";" /ws
                 | ^"kill"     int                    ";" /ws
                 | ^"literal"  Literal  RequeueCount  ";" /ws
                 | RepeatCount Commands RequeueCount ^";" /ws
@@ -28,6 +28,7 @@ RepeatCount     = "" | ^"[*]" | "[" int "]"
 RequeueCount    = ""
                 | "," "requeue" (^"forever" | int ws "times") /ws
 
+Flags:: = Flag +/ (ws "|" ws)
 Flag =  ^"0"
      |  ^"1"
      |  ^"a"
index cabdca4..97f11ef 100644 (file)
@@ -14,6 +14,9 @@ public abstract class InstructionEncoder {
     public static final int WIDTH_CODEBAG_SIZE     = 6;
     public static final int WIDTH_COUNTER_LITERAL  = 6;
 
+    public static final Mask FLAGS               = new Mask("...............000000................");
+    public static final Mask FLAGS_A             = new Mask("...............000000vvvvvvvv........");
+    public static final Mask FLAGS_B             = new Mask("...............000000........vvvvvvvv");
     public static final Mask REPEAT_FROM_DATA    = new Mask("...............000001.........0......");
     public static final Mask REPEAT_FROM_LITERAL = new Mask("...............000001.........1vvvvvv");
     public static final Mask LOOP_FROM_DATA      = new Mask("...............000010.........0......");
@@ -90,6 +93,9 @@ public abstract class InstructionEncoder {
         if (KILL.get(inst))     return new Instruction.Kill(name, (int)(KILL.getval(inst)+1));
         if (LITERAL_LO.get(inst))  return new Instruction.HalfLiteral(name, LITERAL_LO.getval(inst), 0, false);
         if (LITERAL_HI.get(inst))  return new Instruction.HalfLiteral(name, LITERAL_HI.getval(inst), 0, true);
+        if (FLAGS.get(inst))       return new Instruction.SetFlags(name, (int)FLAGS_A.getval(inst), (int)FLAGS_B.getval(inst));
+
+        if (!MOVE.get(inst)) throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
 
         Destination dest    = getDestByAddr(PATH_LITERAL.getval(inst));
         boolean tokenIn     = TI.get(inst);
@@ -138,6 +144,12 @@ public abstract class InstructionEncoder {
         } else if (d instanceof Instruction.Massacre) {
             instr = MASSACRE.set(instr);
 
+        } else if (d instanceof Instruction.SetFlags) {
+            Instruction.SetFlags sf = (Instruction.SetFlags)d;
+            instr = FLAGS.set(instr);
+            instr = FLAGS_A.setval(instr, sf.flag_a);
+            instr = FLAGS_B.setval(instr, sf.flag_b);
+
         } else if (d instanceof Instruction.HalfLiteral) {
             Instruction.HalfLiteral inst = (Instruction.HalfLiteral)d;
             if (inst.pump != null) {
@@ -179,6 +191,9 @@ public abstract class InstructionEncoder {
             }
             if (inst.standing)                   instr = STAND.set(instr);
 
+        } else {
+            throw new RuntimeException("unrecognized instruction " + d);
+
         }
         return instr;
     }
index b600615..b5b0960 100644 (file)
@@ -11,6 +11,9 @@ abstract class InstructionPump extends InterpreterPump {
 
     public int clogged = 0;
 
+    public boolean flag_a = false;
+    public boolean flag_b = false;
+
     /** the currently executing instruction */
     private Instruction executing = null;
 
@@ -96,6 +99,30 @@ abstract class InstructionPump extends InterpreterPump {
         } else if (executing instanceof Instruction.DecrLoop) {
             executing = null;
             return;
+        } else if (executing instanceof Instruction.SetFlags) {
+            Instruction.SetFlags sf = (Instruction.SetFlags)executing;
+            boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0;
+            boolean old_z = oldLoopCounter == 0;
+            boolean old_a = flag_a;
+            boolean old_b = flag_b;
+            flag_a =
+                (((sf.flag_a & sf.FLAG_A)     != 0) ?  old_a : false) |
+                (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+                (((sf.flag_a & sf.FLAG_B)     != 0) ?  old_b : false) |
+                (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+                (((sf.flag_a & sf.FLAG_Z)     != 0) ?  old_z : false) |
+                (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+                (((sf.flag_a & sf.FLAG_S)     != 0) ?  old_s : false) |
+                (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false);
+            flag_b =
+                (((sf.flag_b & sf.FLAG_A)     != 0) ?  old_a : false) |
+                (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+                (((sf.flag_b & sf.FLAG_B)     != 0) ?  old_b : false) |
+                (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+                (((sf.flag_b & sf.FLAG_Z)     != 0) ?  old_z : false) |
+                (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+                (((sf.flag_b & sf.FLAG_S)     != 0) ?  old_s : false) |
+                (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false);
         } else if (executing instanceof Instruction.Clog) {
             clogged++;
             executing = null;