T425 uCode magic

The decoding of the Inmos Transputer ucode (which I extracted from the actual transputer devices using a ucode ROM test access mode) was a very slow and rather painful task. Not only was there very little material on the internet but the decoding of the column drivers often felt like a  case of one step forward and two steps backwards most of the time. 

At the start I worked on the simple instructions which I could determine the column drivers (e.g. rev, ldc, pfix, nfix).  Then I used the instructions which I could determine the destination registers (including the undocumented test instructions). For the arithmetic instructions, I used a TIS appendix paper written by Guy Harriman (from Inmos) and the checkout (early transputer test code) to help with some of the ALU and shifting bits. As time went on it became more a guessing game in figuring out the remaining column driver functions (in particular the link interface controls).

On this web page you will find some details of the Inmos Transputer T425 Rev. C VBC. I don't intend to list the complete T425 VBC (aka ucode).  Oh and by the way, VBC stands for Vogon Banana Code. Refer to my Simple 42 webpage for an explanation.

I have made a start with two of my favourite  instructions since they both use a hidden trick to restore the DataIn register to its original entry value on completion of the instruction. The two instructions are gcall and ret. Also included is the rev instruction since it was one of the first to be decoded. Each instruction (below) has a high-level Occam description, a low-level Occam implementation and the VBC ucode.

For historical purposes, during the development of the T425 Transputer (as with the T414) at Inmos, the VBC ucode was hand written by Guy Harriman and Jon Beecroft, based on a high-level Occam instruction set description document (written by Roger Shepherd and David May). A Functional (or Datapath) simulator was used to test the VBC operation and correctness. The VBC reader and ROM optimiser tools (written by Jim Cownie) were used to reduce the ucode ROM size before being used by the Inmos ROM layout generator tool. To simulate the whole chip a hardware description language (simply called HDL) which included a ROM (loaded with the VBC output) was run on a proprietary Inmos simulation tool. This could run small programs to check it was working as expected. 

GCALL (VBC ucode):
GCALL:        XbusfromIptrReg        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        AregfromZbus        DataRegfromAreg        RETnext2 ;
RETnext2:        XbusfromDataIn        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        IptrRegFromZbus        DataInfromPrevReadReg        RETend ;
RETend:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        OregFrom0        Next ;

GCALL (low-level Occam):
IF  NextInst = GCALL    SEQ        DataReg := Areg      Areg := IptrReg      NextInst := RETnext2
  NextInst = RETnext2    SEQ        IptrReg := DataInReg      DataInReg := PrevReadReg      NextInst := RETend
  NextInst = RETend    SEQ        Oreg := 0      NextInst := 0      

GCALL (high-level Occam):
  SEQ      DataReg := Areg    Areg := IptrReg    IptrReg := DataInReg    DataInReg := PrevReadReg    Oreg := 0    Notes:  DataRegfromAreg actions: PrevReadReg <= DataInReg <= Areg; DataOutReg <= Areg  DataReg (refers to both DataInReg and DataOutReg)  
RET (VBC ucode):
RET:        XbusfromWptrReg        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        MemRead        DataMemAddrFromZbus        RETnext1 ;
RETnext1:        XbusfromWdescReg        YbusfromConstBox    SixteenfromCbox        ZbusFromXbusPlusYbus        WdescRegfromZbus        RETnext2 ;
RETnext2:        XbusfromDataIn        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        IptrRegFromZbus        DataInfromPrevReadReg        RETend ;
RETend:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        OregFrom0        Next ;

RET (low-level Occam):
IF  NextInst = RET    SEQ        RIndexWord (DataMemAddrReg, 0, DataInReg)       NextInst := RETnext1                                             
  NextInst = RETnext1    SEQ        AtWord (WdescReg, 4, WdescReg)         NextInst := RETnext2                                             
  NextInst = RETnext2    SEQ        IptrReg := DataInReg      DataInReg := PrevReadReg       NextInst := RETend                                             
  NextInst = RETend    SEQ        Oreg := 0       NextInst := 0      

RET (high-level Occam):
  SEQ      RIndexWord (Wptr, 0, DataInReg)     AtWord (WdescReg, 4, WdescReg)       IptrReg := DataInReg    DataInReg := PrevReadReg     Oreg := 0     Notes:  MemRead actions: requests a memory interface access in the next cycle: PrevReadReg <= DataInReg <= MemoryWord[DataMemAddrReg]
REV (VBC ucode):
REV:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        AregfromBregSlave        BregfromAregSlave        OregFrom0        Next ;

REV (low-level Occam):
IF  NextInst = REV    SEQ        Areg := Breg.Slave       Breg := Areg.Slave       Oreg := 0       NextInst := 0      

REV (high-level Occam):
  SEQ      Areg := Breg.Slave     Breg := Areg.Slave    Oreg := 0    Notes:  N/A
BSUB (VBC ucode):
BSUB:        XbusfromAreg        YbusfromBreg        ZbusFromXbusPlusYbus        AregfromZbus        BregfromCregSlave        OregFrom0        Next ;

BSUB (low-level Occam):
IF  NextInst = BSUB    SEQ        Areg := Areg + Breg      Breg := Creg.Slave      Oreg := 0      NextInst := 0      

BSUB (high-level Occam):
  SEQ        Areg := Areg + Breg      Breg := Creg.Slave      Oreg := 0
Notes:  N/A
GT (VBC ucode):
GT:        XbusfromAreg        YbusfromBreg        ZbusFromXbusMinusYbus        EregfromZbus        BregfromCregSlave        Cond0FromNotZbusSubLessThan0 (  GTresultFalse,  GTresultTrue ) ;  // [1, 0 case]
GTresultTrue:        XbusfromAreg        YbusfromConstBox    MachineTRUE        ZbusFromYbus        AregfromZbus        OregFrom0        Next ;
GTresultFalse:        XbusfromAreg        YbusfromConstBox    MachineFALSE        ZbusFromYbus        AregfromZbus        OregFrom0        Next ;

GT (low-level Occam):
IF  NextInst = GT    SEQ        Zbus := Areg - Breg      UpdateAluFlags ()      Ereg := Zbus      Breg := Creg.Slave      IF        NotZbusSubLessThan0 = 0          NextInst := GTresultTrue                                                     TRUE          NextInst := GTresultFalse                                             
  NextInst = GTresultTrue    SEQ        Areg := MachineTRUE      Oreg := 0      NextInst := 0      
  NextInst = GTresultFalse    SEQ        Areg := MachineFALSE      Oreg := 0      NextInst := 0      

GT (high-level Occam with transformation for comparision test):
SEQ  -- Ereg := Areg - Breg  IF    ((Areg - Breg) < 0)     -- which is equivalent to Breg > Areg      Areg : = MachineTRUE    TRUE      Areg := MachineFALSE  Breg := Creg.Slave  Oreg := 0

GT (high-level Occam):
SEQ  IF    Breg > Areg      Areg : = MachineTRUE    TRUE      Areg := MachineFALSE  Breg := Creg.Slave  Oreg := 0
Notes:  The t425 transputer hardware conditional multiplexer input is NotZbusSubLessThan0.  NotZbusSubLessThan0 := NOT (Zbus < 0)  Ereg used to hold ALU result for test purposes
CJ (VBC ucode):
CJ:        XbusfromAreg        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        Cond0FromNotZbusEq0 (  CJpopStack,  CJupdateInstReg ) ;  // [1, 0 case]
CJupdateInstReg:        XbusfromIptrReg        YbusfromOreg        ZbusFromXbusPlusYbus        IptrRegFromZbus        RETend ;
RETend:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        OregFrom0        Next ;
CJpopStack:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        AregfromBregSlave        BregfromCregSlave        OregFrom0        Next ;

CJ (low-level Occam):
IF  NextInst = CJ    SEQ        Zbus := Areg      UpdateAluFlags ()      IF        NotZbusEq0 = 0          NextInst = CJupdateInstReg        TRUE          NextInst = CJpopStack
  NextInst = CJupdateInstReg    SEQ      IptrReg := IptrReg + Oreg                                                          Oreg := 0      NextInst := 0      
  NextInst = CJpopStack    SEQ      Areg := Breg.Slave      Breg := Areg.Slave      Oreg := 0      NextInst := 0      

CJ (high-level Occam):
SEQ  IF    Areg = 0      IptrReg := IptrReg + Oreg    TRUE      Areg := Breg.Slave      Breg := Areg.Slave  Oreg := 0
Notes:  The t425 transputer hardware conditional multiplexer input is NotZbusEq0.  NotZbusEq0 := NOT (Zbus = 0)
WCNT (VBC ucode):
WCNT:        XbusfromConstBox    EightfromCbox        YbusfromBreg        ZbusFromMinusXbus        DregfromZbus        BregfromAregSlave        CregfromBregSlave        WCNTtestSign ;
WCNTtestSign:        XbusfromAreg        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        OregfromZbus        Cond1FromBslaveMsb (  WCNTshiftNeg,  WCNTshiftPos ) ;  // [1, 0 case]
WCNTshiftPos:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        ZbusFrom0        ShiftRightBreg        WordIncDreg        Cond0FromNotIncDregCarryOut (  WCNTshiftPos,  WCNTend1 ) ;  // [1, 0 case]
WCNTend1:        XbusfromConstBox    OnesfromCbox        YbusfromOreg        YbusByteSelMask        ZbusFromYbus        BregfromZbus        AregfromBregSlave        OregFrom0        Next ;
WCNTshiftNeg:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        ZbusFromMinus1        ShiftRightBreg        WordIncDreg        Cond0FromNotIncDregCarryOut (  WCNTshiftNeg,  WCNTend2 ) ;  // [1, 0 case]
WCNTend2:        XbusfromConstBox    OnesfromCbox        YbusfromOreg        YbusByteSelMask        ZbusFromYbus        BregfromZbus        AregfromBregSlave        OregFrom0        Next ;

WCNT (low-level Occam):
IF  NextInst = WCNT    SEQ        LoopCount (Dreg, 2)                                             Breg := Areg.Slave                                      Creg := Breg.Slave                                      NextInst :=  WCNTtestSign                                                   NextInst = WCNTtestSign    SEQ        Oreg := Areg                                                         IF                                                        BslaveMsb          NextInst := WCNTshiftNeg        TRUE          NextInst := WCNTshiftPos          NextInst = WCNTshiftPos    SEQ            Zbus := 0      ShiftRightBreg ()                                 WordIncDreg ()                               IF        NotIncDregCarryOut = 0          NextInst := WCNTend1        TRUE          NextInst := WCNTshiftPos                                                      NextInst = WCNTshiftNeg    SEQ            Zbus := -1                                        ShiftRightBreg ()                                 WordIncDreg ()                                IF        NotIncDregCarryOut = 0          NextInst := WCNTend2        TRUE          NextInst := WCNTshiftNeg
  NextInst = WCNTend1    SEQ            Breg := Oreg /\ ByteSelectMask                   Areg := Breg.Slave                          Oreg := 0      NextInst := 0                                                                  NextInst = WCNTend2    SEQ            Breg := Oreg /\ ByteSelectMask                   Areg := Breg.Slave                          Oreg := 0                                   NextInst := 0                                             

WCNT (high-level Occam with transformation for WHILE replacement):
  SEQ      LoopCount (Dreg, 2)      // loops twice     Breg := Areg.Slave    Creg := Breg.Slave    Oreg := Areg
    WCNT_loop:        IF       BslaveMsb        Zbus := -1                  TRUE        Zbus := 0    ShiftRightBreg ()    WordIncDreg ()            IF      NOT (NotIncDregCarryOut = 0)        goto WCNT_loop      TRUE        goto WCNT_end        WCNT_end:            Breg := Oreg /\ ByteSelectMask    Areg := Breg.Slave           Oreg := 0

WCNT (high-level Occam):
  SEQ      LoopCount (Dreg, 2)      // loops twice     Breg := Areg.Slave    Creg := Breg.Slave    Oreg := Areg      WHILE NOT (NotIncDregCarryOut = 0)  // <> 0      SEQ        IF           BslaveMsb            Zbus := -1                      TRUE            Zbus := 0        ShiftRightBreg ()         WordIncDreg ()    Breg := Oreg /\ ByteSelectMask    Areg := Breg.Slave           Oreg := 0
Notes:  The high-level Occam has a WHILE loop which must be replaced during the initial transformation.  ShiftRightBreg () does Breg := (Breg >> 1) \/ ( Zbus /\ #80000000)   WordIncDreg () does Dreg := Dreg + BPW, and updates Dreg carry out flag  LoopCount (Reg, X) does Reg := -X * BPW, and updates Reg carry out flag (macro intended for Dreg or Oreg)  BytesPerWord (BPW) is 4  ByteSelectMask is #00000003  The t425 transputer hardware conditional multiplexer inputs are NotIncDregCarryOut and BslaveMsb.
GAJW (VBC ucode):
GAJW:        XbusfromWptrReg        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        AregfromZbus        DataRegfromAreg        Cond1FromProcPriority (  GAJWprocLow,  GAJWprocHigh ) ;  // [1, 0 case]
GAJWprocHigh:        XbusfromDataIn        YbusfromConstBox    OnesfromCbox        ZbusFromXbus        WdescRegfromZbus        OregFrom0        Next ;
GAJWprocLow:        XbusfromDataIn        YbusfromConstBox    OnesfromCbox        ZbusFromXbusPlus1        WdescRegfromZbus        OregFrom0        Next ;

GAJW (low-level Occam):
IF  NextInst = GAJW    SEQ        DataReg := Areg      Areg := WprtReg      IF        ProcPriority          NextInst = GAJWprocLow        TRUE          NextInst = GAJWprocHigh
  NextInst = GAJWprocLow    SEQ      WdescReg := DataInReg + 1      Oreg := 0      NextInst := 0      
  NextInst = GAJWprocHigh    SEQ      WdescReg := DataInReg      Oreg := 0      NextInst := 0                  GAJW (high-level Occam):
  SEQ      DataReg := Areg    Areg := WprtReg    IF      ProcPriority        WdescReg := DataInReg + 1      TRUE        WdescReg := DataInReg    Oreg := 0
Notes:  The t425 transputer hardware conditional multiplexer input is ProcPriority.  ProcPriority := (WdescReg /\ 1)  DataReg (refers to both DataInReg and DataOutReg)

The following is a reconstruction of the VBC file contents for the T425 Rev. C Transputer (based on my column driver decoding and the text format used by the Simple 42 processor) which would have been initially hand written by the engineers at Inmos, and read by the VBC reader.  The VBC comprised of two files  - the declarations in t425.vbc and the definitions in t425with.vbc. The ROM optimiser tool would have also have read the VBC files, in order to reduce the ROM size and then save results in a new VBC output file. The optimiser tool could determine which entry point instruction addresses were fixed. The remaining non entry point ucode could be repositioned by the optimiser. 

// All the declarations for t425revC.vbcWITH
FIELD  Microword[99,97,78,75,73,70,53:52,46,44]             // X bus source select   XbusfromIptrReg      =  #B1000000000   XbusfromConstBox     =  #B0100000000   XbusfromDreg         =  #B0010000000   XbusfromChannelData  =  #B0001000000   XbusfromDataIn       =  #B0000100000   XbusfromAreg         =  #B0000010000   XbusfromWptrReg      =  #B0000001000   XbusfromWdescReg     =  #B0000000100   XbusfromFPtrReg0     =  #B0000000010   XbusfromFPtrReg1     =  #B0000000001 ;
FIELD  Microword[105:104,96,80,66,59:58,50,48,42,37,35,20]     // Y bus source select   YbusFromOregSL2          =  #B1000000000000   YbusfromOreg             =  #B0100000000000   YbusfromConstBox         =  #B0010000000000   YbusfromEreg             =  #B0001000000000   YbusfromBreg             =  #B0000100000000   YbusFromCregSL1          =  #B0000010000000   YbusfromCreg             =  #B0000001000000   YbusfromBPtrReg0         =  #B0000000100000   YbusfromBPtrReg1         =  #B0000000010000   YbusfromStatusReg        =  #B0000000001000   YbusfromClockReg1        =  #B0000000000100   YbusfromClockReg0        =  #B0000000000010   YbusByteSelMask          =  #B0000000000001 ;
FIELD Microword[21,19:14]                           // Alu operations   ZbusFromXbusPlusYbus             =  #B0011000    // X + Y   ZbusFromXbusPlus1                =  #B0110010    // X + 1   ZbusFromYbusMinus(XbusPlus1)     =  #B1011000    // Y - (X + 1)   ZbusFromXbusPlus0                =  #B0110000    // X   ZbusFromMinusXbus                =  #B1110010    // 0 - X   ZbusFromYbusMinusXbus            =  #B1011010    // Y - X   ZbusFromYbusPlusXbusPlus1        =  #B0011010    // Y + X + 1   ZbusFromXbusMinusYbus            =  #B0100110    // X - Y   ZbusFromMinusYbus                =  #B1100110    // 0 - Y   ZbusFrom0                        =  #B0000001    // 0   ZbusFromNotXbusAndYbus           =  #B0100001    // ~X /\ Y   ZbusFromNotXbus                  =  #B0110001    // ~X   ZbusFromXbusAndYbus              =  #B0001001    // X /\ Y   ZbusFromYbus                     =  #B0101001    // Y   ZbusFromNotXbusOrYbus            =  #B0000101    // ~X \/ Y   ZbusFromXbusXorYbus              =  #B0100101    // X >< Y   ZbusFromNotYbus                  =  #B0010101    // ~Y   ZbusFromXbusOrYbus               =  #B0101101    // X \/ Y   ZbusFromMinus1                   =  #B0111101    // -1   ZbusFromYbusAndNot(BPWminus1)    =  #B0101011    // Y /\ ~(4 - 1)   ZbusFromXbus                     =  #B0001101 ;  // X   SET   ZbusFromOnes                     =  ZbusFromMinus1 ;
FIELD Microword[103,98,79,77,69,65,57,51,49,47,45,43,41,38,36,34,12,8,0]                // Z bus destination select   OregfromZbus             =  #B1000000000000000000   IptrRegFromZbus          =  #B0100000000000000000   EregfromZbus             =  #B0010000000000000000   DregfromZbus             =  #B0001000000000000000   AregfromZbus             =  #B0000100000000000000   BregfromZbus             =  #B0000010000000000000   CregfromZbus             =  #B0000001000000000000   WdescRegfromZbus         =  #B0000000100000000000   BPtrReg0fromZbus         =  #B0000000010000000000   BPtrReg1fromZbus         =  #B0000000001000000000   FPtrReg0fromZbus         =  #B0000000000100000000   FPtrReg1fromZbus         =  #B0000000000010000000   StatusRegfromZbus        =  #B0000000000001000000   TNextReg1fromZbus        =  #B0000000000000100000   ClockReg0&1fromZbus      =  #B0000000000000010000   TNextReg0fromZbus        =  #B0000000000000001000   SelectChannelRegfromZbus =  #B0000000000000000100   ChannelStackfromZbus     =  #B0000000000000000010   DataMemAddrFromZbus      =  #B0000000000000000001 ;
FIELD Microword[67,64,60,56,54]              // A/B/C stack control   AregfromBregSlave        =  #B10000   BregfromAregSlave        =  #B01000   BregfromCregSlave        =  #B00100   CregfromBregSlave        =  #B00010   CregFrom0                =  #B00001 ;
FIELD Microword[68,63:61,55,23:22]        // Shifting control   ShiftRightAreg               =  #B1000000   ShiftLeftBreg                =  #B0100000   BregShIn0From1               =  #B0010000   ShiftRightBreg               =  #B0001000   CregFromZbusSR1              =  #B0000100   CregShInMsbfromCarryOut      =  #B0000010   CregShInMsbfromArithLogic    =  #B0000001 ;
FIELD Microword[27:25]                      // condition select for MIR[0]   Cond0fromROMFeedback0            =  #B000   Cond0FromNotCarryOut             =  #B001   Cond0FromNotZbusSubLessThan0     =  #B010   Cond0FromNotAluPropAll1          =  #B011   Cond0FromOverflow                =  #B100   Cond0FromNotIncOregCarryOut      =  #B101   Cond0FromNotIncDregCarryOut      =  #B110   Cond0FromNotPrInAnalyse          =  #B111 ;
SET   Cond0FromNotZbusEq0              = Cond0FromNotAluPropAll1   Cond0FromNotLastRead             = Cond0FromNotIncOregCarryOut   Cond0FromNotLastWrite            = Cond0FromNotIncDregCarryOut ;
FIELD Microword[30,28,32,31]                // condition select for MIR[1]   Cond1fromROMFeedback1            =  #B0000   Cond1FromDivStep0                =  #B0001   Cond1FromDivStep1                =  #B0010   Cond1FromAslave0                 =  #B0011   Cond1FromBslave0                 =  #B0100   Cond1fromBslave1                 =  #B0101   Cond1FromBslaveMsb               =  #B0110   Cond1FromCslaveMsb               =  #B0111   Cond1FromNotTwoReadsToStart      =  #B1000   Cond1FromProcPriority            =  #B1001   Cond1FromChOrTimerReq            =  #B1011   Cond1FromChNotTimerReq           =  #B1100   Cond1FromHighNotLowReq           =  #B1101   Cond1FromBootFromRomNotLinks     =  #B1010   Cond1FromChannelReadyNotRun      =  #B1110   Cond1FromTimeOutReq              =  #B1111 ;   FIELD Microword[39,33,13]                   // Timer control   ResetTEnabled1               =  #B100   ResetTEnabled0               =  #B010   ResetTimeOutLatch            =  #B001 ;
FIELD Microword[102:100,76]                 // Incrementor control   OregFrom0                    =  #B1000   OregFromZbusSL4              =  #B0100   WordIncOreg                  =  #B0010   WordIncDreg                  =  #B0001 ;
FIELD Microword[109,106,83:81,72:71]        // Interface Control Requests   Next                         =  #B1000000   AregfromDataIn               =  #B0100000   DataInfromPrevReadReg        =  #B0010000   MemWrite                     =  #B0001000   MemRead                      =  #B0000100   DataRegfromZbus              =  #B0000010   DataRegfromAreg              =  #B0000001 ;
FIELD Microword[108:107]                   // Byte move control   ByteWriteStrobeEnable        =  #B10   DataRegfromByteShifter       =  #B01 ;
FIELD Microword[40]                   // Error status   StatusErrorfromOverflow      =  #B1 ;
FIELD Microword[74,11:9,7:1]                   // Channel Control Requests   ChannelDataRegfromUbus               =  #B10000000000   HighPriorityChannelAck               =  #B01000000000   LowPriorityChannelAck                =  #B00100000000   ResetChannel                         =  #B00010000000   ResetChannelReadyNotRunlatch         =  #B00001000000   SetAltEnabledLatch                   =  #B00000100000   ClearAltEnabledLatch                 =  #B00000010000   DisableChannelStatus                 =  #B00000001000   EnableChannelandEnableChannelStatus  =  #B00000000100   ResetChannelRunReqlatch              =  #B00000000010   DataMemAddrfromSelectChannelReg      =  #B00000000001 ;
FIELD Microword[117:110,29,24]                  // loads into MIR   ROMFeedback[0]               =  #B0000000001      ROMFeedback[1]               =  #B0000000010   ROMFeedback[2]               =  #B0000000100   ROMFeedback[3]               =  #B0000001000   ROMFeedback[4]               =  #B0000010000   ROMFeedback[5]               =  #B0000100000   ROMFeedback[6]               =  #B0001000000   ROMFeedback[7]               =  #B0010000000   ROMFeedback[8]               =  #B0100000000   ROMFeedback[9]               =  #B1000000000 ;
FIELD Microword[95:84]                   // Constant box select   bit0fromCbox                =  #B100000000000   bit1fromCbox                =  #B010000000000   bit2fromCbox                =  #B001000000000   bit3fromCbox                =  #B000100000000   bit4fromCbox                =  #B000010000000   bit5fromCbox                =  #B000001000000   bit6fromCbox                =  #B000000100000   bit7fromCbox                =  #B000000010000   bit15to8fromCbox            =  #B000000001000   bit22to16fromCbox           =  #B000000000100   bit30to23fromCbox           =  #B000000000010   bit31fromCbox               =  #B000000000001   Minus1fromCbox              =  #B111111111111   Minus2fromCbox              =  #B011111111111   Minus3fromCbox              =  #B101111111111   Minus4fromCbox              =  #B001111111111   Minus5fromCbox              =  #B110111111111   MinIntfromCbox              =  #B000000000001   MinIntplus1fromCbox         =  #B100000000001   MinIntplus2fromCbox         =  #B010000000001    MinIntplus3fromCbox         =  #B110000000001   ZerofromCbox                =  #B000000000000    OnefromCbox                 =  #B100000000000    TwofromCbox                 =  #B010000000000   ThreefromCbox               =  #B110000000000   FourfromCbox                =  #B001000000000   FivefromCbox                =  #B101000000000   EightfromCbox               =  #B000100000000   SixteenfromCbox             =  #B000010000000   EventfromCbox               =  #B000001000001    // 80000020      ExtendFunctionsfromCbox     =  #B000100100001    // 80000048   Link3InputfromCbox          =  #B001110000001    // 8000001C   ByteMaskfromCbox            =  #B111111110000    // 000000FF   MemStartfromCBox            =  #B000011100001    // 80000070   TptrLoc1fromCbox            =  #B000101000001    // 80000028       TptrLoc0fromCbox            =  #B001001000001    // 80000024   EregIntSaveLocfromCbox      =  #B001000100001    // 80000044   Link3OutputfromCbox         =  #B001100000001    // 8000000C   MostPos                     =  #B111111111110    // 7FFFFFFF   MostPosMinus1               =  #B011111111110    // 7FFFFFFE   WdescIntSavefromCbox        =  #B001101000001    // 8000002C   GotoSNPBitfromCbox          =  #B010000000000    // Status bit 1   IOBitfromCbox               =  #B001000000000    // Status bit 2    MovebitfromCbox             =  #B000100000000    // Status bit 3   TimeDelBitfromCbox          =  #B000010000000    // Status bit 4   TimeInsBitfromCbox          =  #B000001000000    // Status bit 5   DistAndInsBitfromCbox       =  #B000000100000    // Status bit 6   HaltOnErrorBitfromCbox      =  #B000000010000    // Status bit 7   Mov2dallfromCbox            =  #B000000001000    // Status bit 15 to 8   Mov2dnonaerofromCbox        =  #B000000000100    // Status bit 22 to 16   J0BreakFlagfromCbox         =  #B000000000010    // Status bit 30 to 23   ErrorFlagfromCbox           =  #B000000000001    // Status bit 31   DevIdfromCBox               =  #B010000000000 ;  // RevC silicon = 02 (00 - 09)  
SET   OnesfromCbox                = Minus1fromCBox   NotProcess.p                = MinIntfromCbox   Enabling.p                  = MinIntplus1fromCbox   Waiting.p                   = MinIntplus2fromCbox    Ready.p                     = MinIntplus3fromCbox   TimeSet.p                   = MinIntplus1fromCbox   TimeNoSet.p                 = MinIntplus2fromCbox   NoneSelected.o              = Minus1fromCBox       Iptr.s                      = Minus1fromCbox     // -1   Link.s                      = Minus2fromCbox     // -2   State.s                     = Minus3fromCbox     // -3   Pointer.s                   = Minus3fromCbox     // -3   TLink.s                     = Minus4fromCbox     // -4   Time.s                      = Minus5fromCbox     // -5   MachineTRUE                 = OnefromCbox   MachineFALSE                = ZerofromCbox ;   USE "t425with.vbc"      // definitions and predefined instruction label addresses (e.g. REV)
DO
REV:        XbusfromConstBox    OnesfromCbox        YbusfromConstBox        AregfromBregSlave        BregfromAregSlave        OregFrom0        Next ;
LDDEVID:        XbusfromAreg        YbusfromConstBox    DevIdfromCbox        ZbusFromYbus        AregfromZbus        BregfromAregSlave        CregfromBregSlave        OregFrom0        Next ;
// the rest of the t425 VBC code follows ...
// All the definitions for t425revC.vbc
   // Fixed entry point (==opcodes) instruction addressesSET      REV                          = #B0000000000   // 000    LB                           = #B0000000001   // 001    BSUB                         = #B0000000010   // 002    ENDP                         = #B0000000011   // 003    DIFF                         = #B0000000100   // 004    ADD                          = #B0000000101   // 005    GCALL                        = #B0000000110   // 006    IN                           = #B0000000111   // 007    PROD                         = #B0000001000   // 008    GT                           = #B0000001001   // 009    WSUB                         = #B0000001010   // 00A    OUT                          = #B0000001011   // 00B    SUB                          = #B0000001100   // 00C    STARTP                       = #B0000001101   // 00D    OUTBYTE                      = #B0000001110   // 00E    OUTWORD                      = #B0000001111   // 00F    SETERR                       = #B0000010000   // 010                                      RESETCH                      = #B0000010010   // 012    CSUB0                        = #B0000010011   // 013                                      STOPP                        = #B0000010101   // 015    LADD                         = #B0000010110   // 016    STLB                         = #B0000010111   // 017    STHF                         = #B0000011000   // 018    NORM                         = #B0000011001   // 019    LDIV                         = #B0000011010   // 01A    LDPI                         = #B0000011011   // 01B    STLF                         = #B0000011100   // 01C    XDBLE                        = #B0000011101   // 01D    LDPRI                        = #B0000011110   // 01E    REM                          = #B0000011111   // 01F    RET                          = #B0000100000   // 020    LEND                         = #B0000100001   // 021    LDTIMER                      = #B0000100010   // 022    TESTLDS                      = #B0000100011   // 023    TESTLDE                      = #B0000100100   // 024    TESTLDD                      = #B0000100101   // 025    TESTSTS                      = #B0000100110   // 026    TESTSTE                      = #B0000100111   // 027    TESTSTD                      = #B0000101000   // 028    TESTERR                      = #B0000101001   // 029    TESTPRANAL                   = #B0000101010   // 02A    TIN                          = #B0000101011   // 02B    DIV                          = #B0000101100   // 02C    TESTHARDCHAN                 = #B0000101101   // 02D    DIST                         = #B0000101110   // 02E    DISC                         = #B0000101111   // 02F    DISS                         = #B0000110000   // 030    LMUL                         = #B0000110001   // 031    NOT                          = #B0000110010   // 032    XOR                          = #B0000110011   // 033    BCNT                         = #B0000110100   // 034    LSHR                         = #B0000110101   // 035    LSHL                         = #B0000110110   // 036    LSUM                         = #B0000110111   // 037    LSUB                         = #B0000111000   // 038    RUNP                         = #B0000111001   // 039    XWORD                        = #B0000111010   // 03A    SB                           = #B0000111011   // 03B    GAJW                         = #B0000111100   // 03C    SAVEL                        = #B0000111101   // 03D    SAVEH                        = #B0000111110   // 03E    WCNT                         = #B0000111111   // 03F    SHR                          = #B0001000000   // 040    SHL                          = #B0001000001   // 041    MINT                         = #B0001000010   // 042    ALT                          = #B0001000011   // 043    ALTWT                        = #B0001000100   // 044    ALTEND                       = #B0001000101   // 045    AND                          = #B0001000110   // 046    ENBT                         = #B0001000111   // 047    ENBC                         = #B0001001000   // 048    ENBS                         = #B0001001001   // 049    MOVE                         = #B0001001010   // 04A    OR                           = #B0001001011   // 04B    CSNGL                        = #B0001001100   // 04C    CCNT1                        = #B0001001101   // 04D    TALT                         = #B0001001110   // 04E    LDIFF                        = #B0001001111   // 04F    STHB                         = #B0001010000   // 050    TALTWT                       = #B0001010001   // 051    SUM                          = #B0001010010   // 052    MUL                          = #B0001010011   // 053    STTIMER                      = #B0001010100   // 054    STOPERR                      = #B0001010101   // 055    CWORD                        = #B0001010110   // 056    CLRHALTERR                   = #B0001010111   // 057    SETHALTERR                   = #B0001011000   // 058    TESTHALTERR                  = #B0001011001   // 059    DUP                          = #B0001011010   // 05A    MOVE2DINIT                   = #B0001011011   // 05B    MOVE2DALL                    = #B0001011100   // 05C    MOVE2DNONZERO                = #B0001011101   // 05D    MOVE2DZERO                   = #B0001011110   // 05E                                      UNPACKSN                     = #B0001100011   // 063                                      POSTNORMSN                   = #B0001101100   // 06C    ROUNDSN                      = #B0001101101   // 06D                                      LDINF                        = #B0001110001   // 071    FMUL                         = #B0001110010   // 072    CFLERR                       = #B0001110011   // 073    CRCWORD                      = #B0001110100   // 074    CRCBYTE                      = #B0001110101   // 075    BITCNT                       = #B0001110110   // 076    BITREVWORD                   = #B0001110111   // 077    BITREVNBITS                  = #B0001111000   // 078    POP                          = #B0001111001   // 079    TIMERDISABLEH                = #B0001111010   // 07A    TIMERDISABLEL                = #B0001111011   // 07B    TIMERENABLEH                 = #B0001111100   // 07C    TIMERENABLEL                 = #B0001111101   // 07D    LDMEMSTARTVAL                = #B0001111110   // 07E                                      WSUBDB                       = #B0010000001   // 081                                      FPTESTERR                    = #B0010011100   // 09C                                      BREAK                        = #B0010110001   // 0B1    CLRJ0BREAK                   = #B0010110010   // 0B2    SETJ0BREAK                   = #B0010110011   // 0B3    TESTJ0BREAK                  = #B0010110100   // 0B4                                      LDDEVID                      = #B0101111100   // 17C                                     TIMER1REQ                    = #B0111111000   // 1F8   HandleTimerRequest1   TIMER0REQ                    = #B0111111001   // 1F9   HandleTimerRequest0   CHAN1REQ                     = #B0111111010   // 1FA   HandleChannelRequest1   CHAN0REQ                     = #B0111111011   // 1FB   HandleChannelRequest0                                     START                        = #B0111111111   // 1FF    J                            = #B1000000000   // 200    LDLP                         = #B1000000001   // 201    PFIX                         = #B1000000010   // 202    LDNL                         = #B1000000011   // 203    LDC                          = #B1000000100   // 204    LDNLP                        = #B1000000101   // 205    NFIX                         = #B1000000110   // 206    LDL                          = #B1000000111   // 207    ADC                          = #B1000001000   // 208    CALL                         = #B1000001001   // 209    CJ                           = #B1000001010   // 20A    AJW                          = #B1000001011   // 20B    EQC                          = #B1000001100   // 20C    STL                          = #B1000001101   // 20D    STNL                         = #B1000001110   // 20E       // Non-fixed VBC addresses generated by ROM optimiser (list below is not complete)      GAJWprocHigh                 =  #B0100011001   // 119
   GAJWprocLow                  =  #B0100011011   // 11B    CJupdateInstReg              =  #B0100101000   // 128   CJpopStack                   =  #B0100101001   // 129
   WCNTend1                     =  #B0100110000   // 130   WCNTshiftPos                 =  #B0100110001   // 131    WCNTend2                     =  #B0100110010   // 132   WCNTshiftNeg                 =  #B0100110011   // 133
   RETend                       =  #B0111001001   // 1C9 
   GTresultTrue                 =  #B0111100100   // 1E4    GTresultFalse                =  #B0111100101   // 1E5
   RETnext1                     =  #B1000001111   // 20F
   RETnext2                     =  #B1010001010   // 24A
   WCNTtestSign                 =  #B1001101000 ; // 268