add support for a "standing" count value
[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 static final int STANDING = -3;
109         public final int source;
110         public final int dest;
111         public Counter(Pump pump, int source, int dest) { this(pump, P_ALWAYS, source, dest); }
112         public Counter(Pump pump, int predicate, int source, int dest) {
113             super(pump, predicate);
114             this.source = source;
115             this.dest = dest;
116         }
117         public String toString() {
118             if (source==LOOP_COUNTER && dest==DATA_LATCH) return "take loop counter;";
119             StringBuffer ret = new StringBuffer();
120             ret.append("load ");
121             switch(dest) {
122                 case LOOP_COUNTER: ret.append("loop"); break;
123                 case REPEAT_COUNTER: ret.append("repeat"); break;
124                 default: throw new RuntimeException("invalid");
125             }
126             ret.append(" counter");
127             if (source == STANDING)
128                 ret.append(" with *");
129             else if (source >= 0) {
130                 ret.append(" with " + source);
131             } else if (source!=DATA_LATCH) {
132                 throw new RuntimeException("invalid");
133             }
134             ret.append(";");
135             return ret.toString();
136         }
137         public boolean isLooping() { return true; }
138     }
139
140     public static class Move extends PredicatedInstruction {
141         public final Destination dest;
142
143         public final boolean     tokenIn;
144         public final boolean     dataIn;
145         public final boolean     latch;
146         public final boolean     dataOutDest;
147         public final boolean     dataOut;
148         public final boolean     tokenOut;
149         public final boolean     requeue;
150         public final boolean     ignoreUntilLast;
151         public final boolean     standing;
152
153         /** count=0 denotes a standing move */
154         public Move(Pump        pump,
155                     int         predicate,
156                     Destination dest,
157                     int         count,
158                     boolean     tokenIn,
159                     boolean     dataIn,
160                     boolean     latch,
161                     boolean     dataOutDest,
162                     boolean     dataOut,
163                     boolean     tokenOut,
164                     boolean     requeue,
165                     boolean     ignoreUntilLast) {
166             super(pump, predicate);
167             this.dest = dest;
168             this.tokenIn = tokenIn;
169             this.dataIn = dataIn;
170             this.latch = latch;
171             this.dataOutDest = dataOutDest;
172             this.dataOut = dataOut;
173             this.tokenOut = tokenOut;
174             this.requeue = requeue;
175             this.ignoreUntilLast = ignoreUntilLast;
176             this.standing = count==0;
177             if (pump.isInbox() && tokenIn && dataIn)
178                 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
179             if (pump.isOutbox() && tokenOut && dataOut)
180                 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
181             if (latch && !dataIn)
182                 throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
183         }
184
185         public String toString() {
186             // FIXME
187             String ret = super.toString();
188             boolean needcomma = false;
189             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
190             if (dataIn && latch)  {
191                 if (pump.isInbox())
192                     ret += (needcomma ? ", " : "") + "receive";
193                 else
194                     ret += (needcomma ? ", " : "") + "take";
195                 needcomma = true;
196             }
197             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
198             if (dataOut)  {
199                 if (pump.isInbox() || dest==null)
200                     ret += (needcomma ? ", " : "") + "deliver";
201                 else
202                     ret += (needcomma ? ", " : "") + "sendto "+dest;
203                 needcomma = true;
204             }
205             if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; }
206             return ret;
207         }
208
209         public boolean isLooping() { return true; }
210         public boolean isRepeating() { return true; }
211         public boolean isStanding() { return standing; }
212     }
213
214     /*
215     public static class FullLiteral extends Executable {
216         public final long literal;
217         public boolean isRequeueing() { return true; }
218         public HalfLiteral(Pump pump, long literal) {
219             super(pump, 1);
220             this.literal = literal;
221         }
222         public Instruction.Executable decrementCount() {
223             if (count==1) return null;
224             return new FullLiteral(pump, literal, count-1, high);
225         }
226     }
227     */
228
229     public static class HalfLiteral extends PredicatedInstruction {
230         public final long literal;
231         public final boolean high;
232         public boolean isRequeueing() { return true; }
233         public HalfLiteral(Pump pump, int predicate, long literal, int count, boolean high) {
234             super(pump, predicate);
235             this.literal = literal;
236             this.high = high;
237         }
238         public boolean isLooping() { return true; }
239     }
240
241
242     public static class CodeBagDescriptor extends PredicatedInstruction {
243         // address of CBD, relative to address that this instruction was loaded from
244         public final long offset;
245         public final long size;
246         public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, P_ALWAYS, offset, size); }
247         public CodeBagDescriptor(Pump pump, int predicate, long offset, long size) {
248             super(pump, predicate);
249             this.offset = offset;
250             this.size = size;
251         }
252         public String toString() {
253             String off = ""+offset;
254             if (offset > 0) off = "+"+off;
255             return "(CBD @"+off+"+"+size+"): sendto " + pump;
256         }
257     }
258
259 }