eliminate standing bit
[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
152         /** count=0 denotes a standing move */
153         public Move(Pump        pump,
154                     int         predicate,
155                     Destination dest,
156                     boolean     tokenIn,
157                     boolean     dataIn,
158                     boolean     latch,
159                     boolean     dataOutDest,
160                     boolean     dataOut,
161                     boolean     tokenOut,
162                     boolean     requeue,
163                     boolean     ignoreUntilLast) {
164             super(pump, predicate);
165             this.dest = dest;
166             this.tokenIn = tokenIn;
167             this.dataIn = dataIn;
168             this.latch = latch;
169             this.dataOutDest = dataOutDest;
170             this.dataOut = dataOut;
171             this.tokenOut = tokenOut;
172             this.requeue = requeue;
173             this.ignoreUntilLast = ignoreUntilLast;
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     }
209
210     /*
211     public static class FullLiteral extends Executable {
212         public final long literal;
213         public boolean isRequeueing() { return true; }
214         public HalfLiteral(Pump pump, long literal) {
215             super(pump, 1);
216             this.literal = literal;
217         }
218         public Instruction.Executable decrementCount() {
219             if (count==1) return null;
220             return new FullLiteral(pump, literal, count-1, high);
221         }
222     }
223     */
224
225     public static class HalfLiteral extends PredicatedInstruction {
226         public final long literal;
227         public final boolean high;
228         public boolean isRequeueing() { return true; }
229         public HalfLiteral(Pump pump, int predicate, long literal, int count, boolean high) {
230             super(pump, predicate);
231             this.literal = literal;
232             this.high = high;
233         }
234         public boolean isLooping() { return true; }
235     }
236
237
238     public static class CodeBagDescriptor extends PredicatedInstruction {
239         // address of CBD, relative to address that this instruction was loaded from
240         public final long offset;
241         public final long size;
242         public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, P_ALWAYS, offset, size); }
243         public CodeBagDescriptor(Pump pump, int predicate, long offset, long size) {
244             super(pump, predicate);
245             this.offset = offset;
246             this.size = size;
247         }
248         public String toString() {
249             String off = ""+offset;
250             if (offset > 0) off = "+"+off;
251             return "(CBD @"+off+"+"+size+"): sendto " + pump;
252         }
253     }
254
255 }