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