/* yasep/JScore/yasep_conditions.js
created 2009-08-16 by whygee@f-cpu.org
This is the list of the available conditions and the aliases.
*/

Y.conditionTable=[]; // indexed by name, returns object
Y.tableCondition=[]; // indexed by value of the condition field (0 to 7), returns name
Y.tableConditionAll=[]; // indexed by number of declaration (0 to 15...), returns name
Y.maxConditions=0;

Y.newCondition=function(name,val,reg,x) {
  // val is either a number (new condition) or a string (name of the original, aliased condition)
  // reg is either a number (litteral value) or a register name (for the aliases)
  // x is true when no example can be generated with this name.

  if (typeof val=='string') { // it's an alias to another condition
    Y.conditionTable[val][reg]=name;
    // mark that the aliased condition corresponds to an alias when reg is used.
    val = Y.conditionTable[val].val; // lookup, replace val with the real value
  }
  else
    Y.tableCondition[val]=name;
    // only the first/original conditions should be specified by value

  Y.conditionTable[name]={reg:reg,x:x,val:val};

  Y.tableConditionAll[Y.maxConditions++]=name;
}

// these 2 should be used more constructively, like "ready" or "changed"
// on a queue, or reading an I/O pin
Y.newCondition("ALWAYS",  0, 0, true); // default in extended mode

Y.newCondition("NEVER",   1, 0);

Y.newCondition("ZERO",    2);

Y.newCondition("NZ",      3);

Y.newCondition("LSB0",    4);
Y.newCondition("EVEN",    "LSB0", null, true);

Y.newCondition("LSB1",    5);
Y.newCondition("ODD",     "LSB1", null, true);

Y.newCondition("MSB0",    6);
Y.newCondition("POSITIVE","MSB0", null, true);

Y.newCondition("MSB1",    7);
Y.newCondition("NEGATIVE","MSB1", null, true);

// some aliases :
// The order of the definition is important
// because only the last one will be reversible.
Y.newCondition("NO_CARRY", "LSB0", "NPC",true);
Y.newCondition("NO_BORROW","LSB1", "NPC",true);
// "No_carry" and "No_borrow" are excluded from the examples,
// as they are not reversible and will make the opcode autotest fail.

Y.newCondition("CARRY",    "LSB1", "NPC");
Y.newCondition("BORROW",   "LSB0", "NPC");

Y.randomCondition=function(){
  var l,m,n,o,r;
  do {
    l=Math.floor(Math.random()*Y.maxConditions); // number
    m=Y.tableConditionAll[l]; // return a name
    n=Y.conditionTable[m]; // return an object
    if (n.x!=true) {
      o=n.reg; 
      if ((typeof o!='number')&&(typeof o!='string')) {
        r=Y.random_register();
        m+=' '+r;
      }
    }
    // verify that the combination does not match an alias
  } while ((n.x==true) || (typeof n[r]=='string'));
  return m;
}
