public String toString() { return super.toString() + "kill"+(count==1?"":(" "+count))+";"; }
}
- public static class SetFlags extends Instruction {
+ public static class PredicatedInstruction extends Instruction {
+ public static final int P_ALWAYS = 0x0001;
+ public static final int P_IF_A = 0x0002;
+ public static final int P_IF_B = 0x0003;
+ public static final int P_IF_Z = 0x0004;
+
+ public final int predicate;
+ public PredicatedInstruction(Pump pump) { super(pump); this.predicate = P_ALWAYS; }
+ public PredicatedInstruction(Pump pump, int predicate) { super(pump); this.predicate = predicate; }
+ public String toString() {
+ switch(predicate) {
+ case P_ALWAYS: return super.toString();
+ case P_IF_A: return "[a] "+super.toString();
+ case P_IF_B: return "[b] "+super.toString();
+ case P_IF_Z: return "[z] "+super.toString();
+ }
+ throw new Error();
+ }
+ }
+
+ public static class SetFlags extends PredicatedInstruction {
public static final int FLAG_Z = 0x0001;
public static final int FLAG_NOT_Z = 0x0002;
public static final int FLAG_S = 0x0004;
public final int flag_a;
public final int flag_b;
- public SetFlags(Pump pump, int flag_a, int flag_b) {
- super(pump);
+ public SetFlags(Pump pump, int predicate, int flag_a, int flag_b) {
+ super(pump, predicate);
this.flag_a = flag_a;
this.flag_b = flag_b;
}
+ public SetFlags(Pump pump, int flag_a, int flag_b) { this(pump, P_ALWAYS, flag_a, flag_b); }
public boolean isLooping() { return true; }
private String printFlag(int flag) {
}
}
- public static class DecrLoop extends Instruction {
+ public static class DecrLoop extends PredicatedInstruction {
public DecrLoop(Pump pump) { super(pump); }
+ public DecrLoop(Pump pump, int predicate) { super(pump, predicate); }
public boolean isDL() { return true; }
public boolean isLooping() { return true; }
}
- public static class Counter extends Instruction {
+ public static class Counter extends PredicatedInstruction {
public static final int DATA_LATCH = -1;
public static final int REPEAT_COUNTER = -2;
public static final int LOOP_COUNTER = -3;
public final int source;
public final int dest;
- public Counter(Pump pump, int source, int dest) {
- super(pump);
+ public Counter(Pump pump, int source, int dest) { this(pump, P_ALWAYS, source, dest); }
+ public Counter(Pump pump, int predicate, int source, int dest) {
+ super(pump, predicate);
this.source = source;
this.dest = dest;
}
public boolean isLooping() { return true; }
}
- public static class Move extends Instruction {
+ public static class Move extends PredicatedInstruction {
public final Destination dest;
public final boolean tokenIn;
/** count=0 denotes a standing move */
public Move(Pump pump,
- Destination dest,
- int count,
- boolean tokenIn,
- boolean dataIn,
- boolean latch,
- boolean dataOutDest,
- boolean dataOut,
- boolean tokenOut,
- boolean requeue,
- boolean ignoreUntilLast) {
- super(pump);
+ int predicate,
+ Destination dest,
+ int count,
+ boolean tokenIn,
+ boolean dataIn,
+ boolean latch,
+ boolean dataOutDest,
+ boolean dataOut,
+ boolean tokenOut,
+ boolean requeue,
+ boolean ignoreUntilLast) {
+ super(pump, predicate);
this.dest = dest;
this.tokenIn = tokenIn;
this.dataIn = dataIn;
}
*/
- public static class HalfLiteral extends Instruction {
+ public static class HalfLiteral extends PredicatedInstruction {
public final long literal;
public final boolean high;
public boolean isRequeueing() { return true; }
- public HalfLiteral(Pump pump, long literal, int count, boolean high) {
+ public HalfLiteral(Pump pump, long literal, int count, boolean high) { this(pump, P_ALWAYS, literal, count, high); }
+ public HalfLiteral(Pump pump, int predicate, long literal, int count, boolean high) {
super(pump);
this.literal = literal;
this.high = high;
public boolean isLooping() { return true; }
}
- public static class CodeBagDescriptor extends Instruction {
- /** address of CBD, relative to address that this instruction was loaded from */
+
+ public static class CodeBagDescriptor extends PredicatedInstruction {
+ // address of CBD, relative to address that this instruction was loaded from
public final long offset;
public final long size;
- public CodeBagDescriptor(Pump pump, long offset, long size) {
- super(pump);
+ public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, P_ALWAYS, offset, size); }
+ public CodeBagDescriptor(Pump pump, int predicate, long offset, long size) {
+ super(pump, predicate);
this.offset = offset;
this.size = size;
}
OUTER: for(Tree tt : t.child(1)) {
int count = 1;
+ int predicate = Instruction.PredicatedInstruction.P_ALWAYS;
+ if ("[a]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_A;
+ if ("[b]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_B;
+ if ("[z]".equals(tt.child(0).head())) predicate = Instruction.PredicatedInstruction.P_IF_Z;
+ tt = tt.child(1);
if ("unclog".equals(tt.head())) {
cb.add(new Instruction.UnClog(pump));
continue;
else if ("notify".equals(ttt.head())) { tokenOut = true; dest = portReference(ttt.child(0)); }
else if ("notifyLast".equals(ttt.head())) { tokenOut = true; ignoreUntilLast = true; dest = portReference(ttt.child(0)); }
}
- cb.add(new Instruction.Move(pump,
- dest, count, tokenIn, dataIn,
- latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
+ cb.add(new Instruction.Move(pump, Instruction.PredicatedInstruction.P_ALWAYS,
+ dest, count, tokenIn, dataIn,
+ latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
}
}
}
CodeBagDef:: = CodeBagName ":" "{" CodeBagBody "}" /ws
Fiber:: = Pump ":" Instructions /ws
+// FIXME: should not have predicates on clog/unclog/kill/massacre
Instructions:: = Instruction +/ ws
-Instruction = ^"unclog" ";" /ws
+Instruction:: = Predicate InstructionX
+Predicate = "" | ^"[a]" ws | ^"[b]" ws | ^"[z]" ws
+InstructionX = ^"unclog" ";" /ws
| ^"clog" ";" /ws
| ^"massacre" ";" /ws
| ^"kill" ";" /ws
boolean standing = STAND.get(inst);
boolean dataOutDest = PATH_DATA.get(inst);
return new Instruction.Move(name,
+ Instruction.PredicatedInstruction.P_ALWAYS, /* FIXME */
dest,
standing?0:1,
tokenIn,
if (executing==null && instructions.size() > 0) executing = instructions.remove();
if (executing==null) return;
- int oldLoopCounter = loopCounter;
- if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1);
-
- if (executing instanceof Instruction.Counter) {
- Instruction.Counter ic = (Instruction.Counter)executing;
- if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
- setDataLatch(oldLoopCounter); /* FIXME: which is correct here? */
- } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
- loopCounter = (int)peekDataLatch();
- } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
- repeatCounter = (int)peekDataLatch();
- } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
- loopCounter = ic.source;
- } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
- repeatCounter = ic.source;
- }
-
- } else if (executing instanceof Instruction.DecrLoop) {
-
- } else if (executing instanceof Instruction.SetFlags) {
- Instruction.SetFlags sf = (Instruction.SetFlags)executing;
- boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0;
- boolean old_z = oldLoopCounter == 0;
- boolean old_a = flag_a;
- boolean old_b = flag_b;
- flag_a =
- (((sf.flag_a & sf.FLAG_A) != 0) ? old_a : false) |
- (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
- (((sf.flag_a & sf.FLAG_B) != 0) ? old_b : false) |
- (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
- (((sf.flag_a & sf.FLAG_Z) != 0) ? old_z : false) |
- (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
- (((sf.flag_a & sf.FLAG_S) != 0) ? old_s : false) |
- (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false);
- flag_b =
- (((sf.flag_b & sf.FLAG_A) != 0) ? old_a : false) |
- (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
- (((sf.flag_b & sf.FLAG_B) != 0) ? old_b : false) |
- (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
- (((sf.flag_b & sf.FLAG_Z) != 0) ? old_z : false) |
- (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
- (((sf.flag_b & sf.FLAG_S) != 0) ? old_s : false) |
- (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false);
- } else if (executing instanceof Instruction.Clog) {
+ if (executing instanceof Instruction.Clog) {
clogged++;
executing = null;
return;
- } else {
- if (!service(executing)) return;
+ }
+
+ boolean enabled = true;
+ if (executing instanceof Instruction.PredicatedInstruction) {
+ Instruction.PredicatedInstruction ip = (Instruction.PredicatedInstruction)executing;
+ switch(ip.predicate) {
+ case Instruction.PredicatedInstruction.P_ALWAYS: enabled = true; break;
+ case Instruction.PredicatedInstruction.P_IF_A: enabled = flag_a; break;
+ case Instruction.PredicatedInstruction.P_IF_B: enabled = flag_b; break;
+ case Instruction.PredicatedInstruction.P_IF_Z: enabled = loopCounter==0; break;
+ }
+ }
+
+ int oldLoopCounter = loopCounter;
+ if (enabled) {
+ if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1);
+
+ if (executing instanceof Instruction.Counter) {
+ Instruction.Counter ic = (Instruction.Counter)executing;
+ if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
+ setDataLatch(oldLoopCounter); /* FIXME: which is correct here? */
+ } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
+ loopCounter = (int)peekDataLatch();
+ } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
+ repeatCounter = (int)peekDataLatch();
+ } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
+ loopCounter = ic.source;
+ } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
+ repeatCounter = ic.source;
+ }
+
+ } else if (executing instanceof Instruction.SetFlags) {
+ Instruction.SetFlags sf = (Instruction.SetFlags)executing;
+ boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0;
+ boolean old_z = oldLoopCounter == 0;
+ boolean old_a = flag_a;
+ boolean old_b = flag_b;
+ flag_a =
+ (((sf.flag_a & sf.FLAG_A) != 0) ? old_a : false) |
+ (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+ (((sf.flag_a & sf.FLAG_B) != 0) ? old_b : false) |
+ (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+ (((sf.flag_a & sf.FLAG_Z) != 0) ? old_z : false) |
+ (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+ (((sf.flag_a & sf.FLAG_S) != 0) ? old_s : false) |
+ (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false);
+ flag_b =
+ (((sf.flag_b & sf.FLAG_A) != 0) ? old_a : false) |
+ (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
+ (((sf.flag_b & sf.FLAG_B) != 0) ? old_b : false) |
+ (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
+ (((sf.flag_b & sf.FLAG_Z) != 0) ? old_z : false) |
+ (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) |
+ (((sf.flag_b & sf.FLAG_S) != 0) ? old_s : false) |
+ (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false);
+ } else if (executing instanceof Instruction.DecrLoop) {
+ } else {
+ if (!service(executing)) return;
+ }
}
if (executing==null) return;