add predicates to instruction encoder/decoder
[fleet.git] / src / edu / berkeley / fleet / api / Instruction.java
1 package edu.berkeley.fleet.api;
2
3 public abstract class Instruction {
4
5     public final Pump pump;
6     public Instruction(Pump pump) { this.pump = pump; }
7     public String toString() { return pump+": "; }
8
9     public boolean isLooping() { return true; }
10     public boolean isRepeating() { return false; }
11     public boolean isStanding() { return false; }
12     public boolean isSK() { return false; }
13     public boolean isDL() { return false; }
14
15     public static class Clog extends Instruction {
16         public Clog(Pump pump) { super(pump); }
17         public String toString() { return super.toString() + "clog;"; }
18         public boolean isLooping() { return false; }
19     }
20
21     public static class UnClog extends Instruction {
22         public UnClog(Pump pump) { super(pump); }
23         public String toString() { return super.toString() + "unclog;"; }
24     }
25
26     public static class Massacre extends Instruction {
27         public Massacre(Pump pump) { super(pump); }
28     }
29
30     public static class Kill extends Instruction {
31         public final int count;
32         public Kill(Pump pump, int count) { super(pump); this.count = count; }
33         public String toString() { return super.toString() + "kill"+(count==1?"":(" "+count))+";"; }
34     }
35
36     public static class PredicatedInstruction extends Instruction {
37         public static final int P_ALWAYS = 0x0001;
38         public static final int P_IF_A   = 0x0002;
39         public static final int P_IF_B   = 0x0003;
40         public static final int P_IF_Z   = 0x0004;
41
42         public final int predicate;
43         public PredicatedInstruction(Pump pump, int predicate) { super(pump); this.predicate = predicate; }
44         public String toString() {
45             switch(predicate) {
46                 case P_ALWAYS: return        super.toString();
47                 case P_IF_A:   return "[a] "+super.toString();
48                 case P_IF_B:   return "[b] "+super.toString();
49                 case P_IF_Z:   return "[z] "+super.toString();
50             }
51             throw new Error();
52         }
53     }
54
55     public static class SetFlags extends PredicatedInstruction {
56         public static final int FLAG_Z     = 0x0001;
57         public static final int FLAG_NOT_Z = 0x0002;
58         public static final int FLAG_S     = 0x0004;
59         public static final int FLAG_NOT_S = 0x0008;
60         public static final int FLAG_B     = 0x0010;
61         public static final int FLAG_NOT_B = 0x0020;
62         public static final int FLAG_A     = 0x0040;
63         public static final int FLAG_NOT_A = 0x0080;
64
65         public final int flag_a;
66         public final int flag_b;
67         public SetFlags(Pump pump, int predicate, int flag_a, int flag_b) {
68             super(pump, predicate);
69             this.flag_a = flag_a;
70             this.flag_b = flag_b;
71         }
72         public SetFlags(Pump pump, int flag_a, int flag_b) { this(pump, P_ALWAYS, flag_a, flag_b); }
73
74         public boolean isLooping() { return true; }
75         private String printFlag(int flag) {
76             if (flag==0) return "0";
77             if ((flag & (FLAG_Z | FLAG_NOT_Z)) == (FLAG_Z | FLAG_NOT_Z)) return "1";
78             if ((flag & (FLAG_B | FLAG_NOT_B)) == (FLAG_B | FLAG_NOT_B)) return "1";
79             if ((flag & (FLAG_A | FLAG_NOT_A)) == (FLAG_A | FLAG_NOT_A)) return "1";
80             if ((flag & (FLAG_S | FLAG_NOT_S)) == (FLAG_S | FLAG_NOT_S)) return "1";
81             String ret = "";
82             if ((flag & FLAG_A)     != 0) ret += (ret.length()>=0?"|":"") +  "a";
83             if ((flag & FLAG_NOT_A) != 0) ret += (ret.length()>=0?"|":"") + "!a";
84             if ((flag & FLAG_B)     != 0) ret += (ret.length()>=0?"|":"") +  "b";
85             if ((flag & FLAG_NOT_B) != 0) ret += (ret.length()>=0?"|":"") + "!b";
86             if ((flag & FLAG_S)     != 0) ret += (ret.length()>=0?"|":"") +  "s";
87             if ((flag & FLAG_NOT_S) != 0) ret += (ret.length()>=0?"|":"") + "!s";
88             if ((flag & FLAG_Z)     != 0) ret += (ret.length()>=0?"|":"") +  "z";
89             if ((flag & FLAG_NOT_Z) != 0) ret += (ret.length()>=0?"|":"") + "!z";
90             return ret;
91         }
92         public String toString() {
93             return super.toString() + " setflags a=" + printFlag(flag_a) + ", b=" + printFlag(flag_b);
94         }
95     }
96
97     public static class DecrLoop extends PredicatedInstruction {
98         public DecrLoop(Pump pump) { super(pump, P_ALWAYS); }
99         public DecrLoop(Pump pump, int predicate) { super(pump, predicate); }
100         public boolean isDL() { return true; }
101         public boolean isLooping() { return true; }
102     }
103
104     public static class Counter extends PredicatedInstruction {
105         public static final int DATA_LATCH = -1;
106         public static final int REPEAT_COUNTER = -2;
107         public static final int LOOP_COUNTER = -3;
108         public final int source;
109         public final int dest;
110         public Counter(Pump pump, int source, int dest) { this(pump, P_ALWAYS, source, dest); }
111         public Counter(Pump pump, int predicate, int source, int dest) {
112             super(pump, predicate);
113             this.source = source;
114             this.dest = dest;
115         }
116         public String toString() {
117             if (source==LOOP_COUNTER && dest==DATA_LATCH) return "take loop counter;";
118             StringBuffer ret = new StringBuffer();
119             ret.append("load ");
120             switch(dest) {
121                 case LOOP_COUNTER: ret.append("loop"); break;
122                 case REPEAT_COUNTER: ret.append("repeat"); break;
123                 default: throw new RuntimeException("invalid");
124             }
125             ret.append(" counter");
126             if (source >= 0) {
127                 ret.append(" with " + source);
128             } else if (source!=DATA_LATCH) {
129                 throw new RuntimeException("invalid");
130             }
131             ret.append(";");
132             return ret.toString();
133         }
134         public boolean isLooping() { return true; }
135     }
136
137     public static class Move extends PredicatedInstruction {
138         public final Destination dest;
139
140         public final boolean     tokenIn;
141         public final boolean     dataIn;
142         public final boolean     latch;
143         public final boolean     dataOutDest;
144         public final boolean     dataOut;
145         public final boolean     tokenOut;
146         public final boolean     requeue;
147         public final boolean     ignoreUntilLast;
148         public final boolean     standing;
149
150         /** count=0 denotes a standing move */
151         public Move(Pump        pump,
152                     int         predicate,
153                     Destination dest,
154                     int         count,
155                     boolean     tokenIn,
156                     boolean     dataIn,
157                     boolean     latch,
158                     boolean     dataOutDest,
159                     boolean     dataOut,
160                     boolean     tokenOut,
161                     boolean     requeue,
162                     boolean     ignoreUntilLast) {
163             super(pump, predicate);
164             this.dest = dest;
165             this.tokenIn = tokenIn;
166             this.dataIn = dataIn;
167             this.latch = latch;
168             this.dataOutDest = dataOutDest;
169             this.dataOut = dataOut;
170             this.tokenOut = tokenOut;
171             this.requeue = requeue;
172             this.ignoreUntilLast = ignoreUntilLast;
173             this.standing = count==0;
174             if (pump.isInbox() && tokenIn && dataIn)
175                 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
176             if (pump.isOutbox() && tokenOut && dataOut)
177                 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
178             if (latch && !dataIn)
179                 throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
180         }
181
182         public String toString() {
183             // FIXME
184             String ret = super.toString();
185             boolean needcomma = false;
186             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
187             if (dataIn && latch)  {
188                 if (pump.isInbox())
189                     ret += (needcomma ? ", " : "") + "receive";
190                 else
191                     ret += (needcomma ? ", " : "") + "take";
192                 needcomma = true;
193             }
194             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
195             if (dataOut)  {
196                 if (pump.isInbox() || dest==null)
197                     ret += (needcomma ? ", " : "") + "deliver";
198                 else
199                     ret += (needcomma ? ", " : "") + "sendto "+dest;
200                 needcomma = true;
201             }
202             if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; }
203             return ret;
204         }
205
206         public boolean isLooping() { return true; }
207         public boolean isRepeating() { return true; }
208         public boolean isStanding() { return standing; }
209     }
210
211     /*
212     public static class FullLiteral extends Executable {
213         public final long literal;
214         public boolean isRequeueing() { return true; }
215         public HalfLiteral(Pump pump, long literal) {
216             super(pump, 1);
217             this.literal = literal;
218         }
219         public Instruction.Executable decrementCount() {
220             if (count==1) return null;
221             return new FullLiteral(pump, literal, count-1, high);
222         }
223     }
224     */
225
226     public static class HalfLiteral extends PredicatedInstruction {
227         public final long literal;
228         public final boolean high;
229         public boolean isRequeueing() { return true; }
230         public HalfLiteral(Pump pump, int predicate, long literal, int count, boolean high) {
231             super(pump, predicate);
232             this.literal = literal;
233             this.high = high;
234         }
235         public boolean isLooping() { return true; }
236     }
237
238
239     public static class CodeBagDescriptor extends PredicatedInstruction {
240         // address of CBD, relative to address that this instruction was loaded from
241         public final long offset;
242         public final long size;
243         public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, P_ALWAYS, offset, size); }
244         public CodeBagDescriptor(Pump pump, int predicate, long offset, long size) {
245             super(pump, predicate);
246             this.offset = offset;
247             this.size = size;
248         }
249         public String toString() {
250             String off = ""+offset;
251             if (offset > 0) off = "+"+off;
252             return "(CBD @"+off+"+"+size+"): sendto " + pump;
253         }
254     }
255
256 }