-- Description of IO processor

Instruction: TYPE = MACHINE DEPENDENT RECORD [
   SELECT Bit0: {NonALUGroup, ALUGroup} 
      ALUGroup => [opcode: Opcode, mode: Mode, reg: Reg, aux: [0..377B]],
      NonALUGroup => [
         SELECT Bit1: {NonShiftGroup, ShiftGroup} FROM
            ShiftGroup => [
               SELECT Bit2to4: {Store, Special, BothRotate0, BothRotate1, RoLsh, 
                 R1Lsh, RoRotate, R1Rotate} FROM
                  Store => [mode: Mode, reg: Reg, aux: [0..377B]],
                  Special => [
                     SELECT Bit5: {Control, Flags} FROM
                        Control => [
                           SELECT Bit6: {Pops, Parity} FROM
                              Pops => [
                                 SELECT Bit7: {Return, Pop} FROM
                                    Return => [fill: [0..377B]],
                                    Pop => [fill: [0..377B]],
                                 ENDCASE-- Bit7--],--Pops
                              Parity => [reg: Reg, fill: [0..377B]],
                           ENDCASE-- Bit6--],--Control
                        Flags => [s: {ClearFlag, SetFlag}, f: {Flag0, Flag1}]
                     ENDCASE-- Bit5--]-- Special
               ENDCASE => [direction: {left, right}, amount: [0..3]]--Bit2to4--
            ],--ShiftGroup
            NonShiftGroup => [
               SELECT Bit2: {Transfer, ConditionalJump} FROM
                  Transfer => [Bit3: {Jump, Call}, addr: [0..7777B]],
                  ConditionalJump => [invert: BOOLEAN, condtion: [0..17B], 
                    addr: [0..377B]]
               ENDCASE--Bit2--]--NonShiftGroup
         ENDCASE--Bit1--]--NonALUGroup
   ENDCASE];--Instruction

IOProc = DEFINITION {
   IN BUSIN(8), Reset, CLC, HalfCLC, MCT, CondIn
   OUT BUSOUT(8), ADDR(12), RAMCE, RAMWE, REGCE, REGWE, CondSel(3), 
      FPD, FWE
   STATE Memory, inst, pc, ar
   GUARDIAN
   DATAFLOW
   CONTROL
      repeat {
         when MCT↑:
            if Reset then {pc ← 6000B; LOOP};
         
         inst ← Memory[pc];

         WITH s: inst SELECT FROM
            ALUGroup => {m;
               m ← SELECT s.mode FROM
                        0 => Memory[ho[pc]+s.aux],
                        1 => Memory[s.aux],
                        2 => Memory[ar],
                        3 => Memory[s.aux]
                     ENDCASE;
               SELECT s.opcode FROM
                  0 => s.reg ← s.reg#m;
                  1 => s.reg ← ~(s.reg#m);
                  2 => s.reg ← ~m;
                  3 => s.reg ← m;
                  4 => s.reg ← ~(s.reg|m);
                  5 => s.reg ← (~s.reg)&m;
                  6 => s.reg ← s.reg&~m;
                  7 => s.reg ← s.reg&m;
                  10B => s.reg ← ~(s.reg&m);
                  11B => s.reg ← (~s.reg)|m;
                  12B => s.reg ← s.reg|~m;
                  13B => s.reg ← s.reg|m;
                  14B => s.reg ← s.reg+m;
                  15B => s.reg ← s.reg-m;
                  16B => s.reg ← m-s.reg;
                  17B => s.reg ← -(s.reg+m)-1
               ENDCASE
            }; -- ALUGroup
            NonALUGroup => {
               WITH t: s SELECT FROM
                  NonShiftGroup => {
                     WITH u: t SELECT FROM
                        Transfer => {
                           SELECT Bit3 FROM
                              Jump => {pc ← u.addr; LOOP},
                              Call => {push[pc]; pc ← u.addr; LOOP}
                           ENDCASE}; -- Transfer
                        CondtionalJump => {
                           SELECT u.condition FROM
                              0 => cond ← R0=0;
                              1 => cond ← R1=0;
                              2 => cond ← R0<0;
                              3 => cond ← R1<0;
                              4 => cond ← R0 Carry;
                              5 => cond ← R1 Carry;
                              6 => cond ← Flag0;
                              7 => cond ← Flag1;
                           ENDCASE => 
                              {CondSel ← u.condition-10B; cond ← CondIn};
                           IF u.invert THEN cond ← ~cond;
                           IF cond THEN {pc ← u.addr+ho[pc]; LOOP}
                     ENDCASE}; -- NonShiftGroup
                  ShiftGroup => {
                     WITH u: t SELECT FROM
                        Store => {
                           addr ← SELECT u.mode FROM
                              0 => ho[pc]+u.aux;
                              1 => u.aux;
                              2 => ar;
                              3 => ERROR;
                              ENDCASE;
                           Memory[addr] ← IF u.reg=R0 THEN R0 ELSE R1
                        }; --ShiftGroup
                        Special => {
                           WITH v:u SELECT FROM
                              Control => {
                                 WITH w:v SELECT FROM
                                    Pops => {
                                       WITH x:w SELECT FROM
                                          Return => {pc ← pop[]; LOOP};
                                          Pop => [] ← pop[]
                                       ENDCASE};-- Pops
                                    Flags => {
                                       SELECT w.s FROM
                                          ClearFlag => {
                                             IF v.flag = Flag0 THEN Flag0 ← 0
                                             ELSE Flag1 ← 0};
                                          SetFlag => {
                                             IF v.flag = Flag0 THEN Flag0 ← 1
                                             ELSE Flag1 ← 1}
                                       ENDCASE}-- Flags
                                 ENDCASE}--Control
                        };--Special
                        BothRotate0, BothRotate1 => 
                           Rotate[reg: R0::R1, direction: u.direction, 
                             amount: u.amount+1];
                        R0Lsh => Shift[reg: R0, direction: u.direction,  
                             amount: u.amount+1];
                        R1Lsh => Shift[reg: R1, direction: u.direction,  
                             amount: u.amount+1];
                        R0Rotate => Rotate[reg: R0, direction: u.direction,  
                             amount: u.amount+1];
                        R1Rotate => Rotate[reg: R0, direction: u.direction,  
                             amount: u.amount+1];
                     ENDCASE}; --ShiftGroup
               ENDCASE}; --NonALUGroup
         ENDCASE;

         pc ← pc+1;
      }--repeat