add SetFlags instruction to API and interpreter
[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     }
80
81     public static class Counter extends Instruction {
82         public static final int DATA_LATCH = -1;
83         public static final int REPEAT_COUNTER = -2;
84         public static final int LOOP_COUNTER = -3;
85         public final int source;
86         public final int dest;
87         public Counter(Pump pump, int source, int dest) {
88             super(pump);
89             this.source = source;
90             this.dest = dest;
91         }
92         public String toString() {
93             if (source==LOOP_COUNTER && dest==DATA_LATCH) return "take loop counter;";
94             StringBuffer ret = new StringBuffer();
95             ret.append("load ");
96             switch(dest) {
97                 case LOOP_COUNTER: ret.append("loop"); break;
98                 case REPEAT_COUNTER: ret.append("repeat"); break;
99                 default: throw new RuntimeException("invalid");
100             }
101             ret.append(" counter");
102             if (source >= 0) {
103                 ret.append(" with " + source);
104             } else if (source!=DATA_LATCH) {
105                 throw new RuntimeException("invalid");
106             }
107             ret.append(";");
108             return ret.toString();
109         }
110         public boolean isLooping() { return true; }
111     }
112
113     public static class Move extends Instruction {
114         public final Destination dest;
115
116         public final boolean     tokenIn;
117         public final boolean     dataIn;
118         public final boolean     latch;
119         public final boolean     dataOutDest;
120         public final boolean     dataOut;
121         public final boolean     tokenOut;
122         public final boolean     requeue;
123         public final boolean     ignoreUntilLast;
124         public final boolean     standing;
125
126         /** count=0 denotes a standing move */
127         public Move(Pump        pump,
128                           Destination dest,
129                           int         count,
130                           boolean     tokenIn,
131                           boolean     dataIn,
132                           boolean     latch,
133                           boolean     dataOutDest,
134                           boolean     dataOut,
135                           boolean     tokenOut,
136                           boolean     requeue,
137                           boolean     ignoreUntilLast) {
138             super(pump);
139             this.dest = dest;
140             this.tokenIn = tokenIn;
141             this.dataIn = dataIn;
142             this.latch = latch;
143             this.dataOutDest = dataOutDest;
144             this.dataOut = dataOut;
145             this.tokenOut = tokenOut;
146             this.requeue = requeue;
147             this.ignoreUntilLast = ignoreUntilLast;
148             this.standing = count==0;
149             if (pump.isInbox() && tokenIn && dataIn)
150                 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
151             if (pump.isOutbox() && tokenOut && dataOut)
152                 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
153             if (latch && !dataIn)
154                 throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
155         }
156
157         public String toString() {
158             // FIXME
159             String ret = super.toString();
160             boolean needcomma = false;
161             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
162             if (dataIn && latch)  {
163                 if (pump.isInbox())
164                     ret += (needcomma ? ", " : "") + "receive";
165                 else
166                     ret += (needcomma ? ", " : "") + "take";
167                 needcomma = true;
168             }
169             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
170             if (dataOut)  {
171                 if (pump.isInbox() || dest==null)
172                     ret += (needcomma ? ", " : "") + "deliver";
173                 else
174                     ret += (needcomma ? ", " : "") + "sendto "+dest;
175                 needcomma = true;
176             }
177             if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; }
178             return ret;
179         }
180
181         public boolean isLooping() { return true; }
182         public boolean isRepeating() { return true; }
183         public boolean isStanding() { return standing; }
184     }
185
186     /*
187     public static class FullLiteral extends Executable {
188         public final long literal;
189         public boolean isRequeueing() { return true; }
190         public HalfLiteral(Pump pump, long literal) {
191             super(pump, 1);
192             this.literal = literal;
193         }
194         public Instruction.Executable decrementCount() {
195             if (count==1) return null;
196             return new FullLiteral(pump, literal, count-1, high);
197         }
198     }
199     */
200
201     public static class HalfLiteral extends Instruction {
202         public final long literal;
203         public final boolean high;
204         public boolean isRequeueing() { return true; }
205         public HalfLiteral(Pump pump, long literal, int count, boolean high) {
206             super(pump);
207             this.literal = literal;
208             this.high = high;
209         }
210         public boolean isLooping() { return true; }
211     }
212
213     public static class CodeBagDescriptor extends Instruction {
214         /** address of CBD, relative to address that this instruction was loaded from */
215         public final long offset;
216         public final long size;
217         public CodeBagDescriptor(Pump pump, long offset, long size) {
218             super(pump);
219             this.offset = offset;
220             this.size = size;
221         }
222         public String toString() {
223             String off = ""+offset;
224             if (offset > 0) off = "+"+off;
225             return "(CBD @"+off+"+"+size+"): sendto " + pump;
226         }
227     }
228
229 }