/***********************************************************************
*
* posop.c - IBM 7090 emulator positive opcode routines.
*
* Changes:
*   ??/??/??   PRP   Original.
*   10/20/03   DGP   Added 7094 instructions.
*   01/28/05   DGP   Revamped channel and tape controls.
*   
***********************************************************************/

#define EXTERN extern

#include <stdio.h>

#include "sysdef.h"
#include "regs.h"
#include "s709.h"
#include "arith.h"
#include "chan.h"
#include "io.h"
#include "posop.h"

extern char errview[5][81];

void
posop()
{
   register chan;
   register dev;

   switch(op)
   {

   case 0000000:   /* HTR */
      stop = 1;
      cycle_count++;
      ic--;
      break;

   case 0000020:   /* TRA */
      if (trap)
      {
         traptrace();
         ic = 00001;
      }
      else
      {
         ic = y;
      }
      break;

   case 0000021:   /* TTR */
      ic = y;
      break;

   case 0000022:   /* TRCA */
      chan = 0;
      goto trcx;
   case 0000024:   /* TRCC */
      chan = 2;
      goto trcx;
   case 0000026:   /* TRCE */
      chan = 4;
      goto trcx;
   case 0000027:   /* TRCG */
      chan = 6;
   trcx:
#ifdef DEBUGIO1
      fprintf (stderr,
	       "TRC Channel %c, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + chan, ctrap_enb, trap, channel[chan].ceof);
#endif
      if (ctrap_enb & (01000000 << chan))
         break;
      if (trap)
         traptrace();
      if (channel[chan].cchk)
      {
         channel[chan].cchk = 0;
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000030:   /* TEFA */
   case 0000031:   /* TEFC */
   case 0000032:   /* TEFE */
   case 0000033:   /* TEFG */
      chan = (op & 03) << 1;
#ifdef DEBUGIO
      fprintf (stderr,
	    "TEF Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + chan, ic, ctrap_enb, trap, channel[chan].ceof);
#endif
      if (ctrap_enb & (1 << chan))
         break;
      if (trap)
         traptrace();
      if (channel[chan].ceof)
      {
         channel[chan].ceof = 0;
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000040:   /* TLQ */
      if (trap)
         traptrace();
      if ((ach & SIGN) == 0)
      {
         if ((mqh & SIGN) == 0)
	 {
            if ( (ach & (Q|P|HMSK)) > (mqh & HMSK) )
               goto tlqtr;
            if ( (ach & (Q|P|HMSK)) < (mqh & HMSK) )
               break;
            if ( acl > mql )
               goto tlqtr;
            break;
         }
	 else
	 {
            goto tlqtr;
         }
      }
      else
      {
         if ((mqh & SIGN) == 0)
	 {
            break;
         }
	 else
	 {
            if ( (ach & (Q|P|HMSK)) > (mqh & HMSK) )
               break;
            if ( (ach & (Q|P|HMSK)) < (mqh & HMSK) )
               goto tlqtr;
            if ( acl > mql )
               break;
            if ( acl < mql )
               goto tlqtr;
            break;
         }
      }
tlqtr: if (trap)
         ic = 00001;
      else
         ic = y;
      break;

   case 0000041:   /* IIA */
      sih ^= ach & (P|HMSK);
      sil ^= acl;
      break;

   case 0000042:   /* TIO */
      if (trap)
         traptrace();
      if ( ((ach & (P|HMSK)) & sih) == (ach & (P|HMSK)) && (acl & sil) == acl )
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      CYCLE();
      break;

   case 0000043:   /* OAI */
      sih |= ach & (P|HMSK);
      sil |= acl;
      break;

   case 0000044:   /* PAI */
      sih = ach & (P|HMSK);
      sil = acl;
      break;

   case 0000046:   /* TIF */
      if (trap)
         traptrace();
      if ( ((ach & (P|HMSK)) & ~sih) == (ach & (P|HMSK)) &&
           (acl & ~sil) == acl )
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      CYCLE();
      break;

   case 0000051:   /* IIR */
      sil ^= srl & 0777777;
      break;

   case 0000054:   /* RFT */
      if ( ((srl & 0777777) & ~sil) == (srl & 0777777) )
         ic++;
      DCYCLE();
      DCYCLE();
      break;

   case 0000055:   /* SIR */
      sil |= srl & 0777777;
      break;

   case 0000056:   /* RNT */
      if ( ((srl & 0777777) & sil) == (srl & 0777777) )
         ic++;
      DCYCLE();
      DCYCLE();
      break;

   case 0000057:   /* RIR */
      sil &= ~(srl & 0777777);
      break;

   case 0000060:   /* TCOA */
   case 0000061:   /* TCOB */
   case 0000062:   /* TCOC */
   case 0000063:   /* TCOD */
   case 0000064:   /* TCOE */
   case 0000065:   /* TCOF */
   case 0000066:   /* TCOG */
   case 0000067:   /* TCOH */
      if (trap)
         traptrace();
      chan = op & 07;
      if (channel[chan].csel)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000074:   /* TSX */
      if (stop)
         setxr(-(ic));
      else
         setxr(-(ic-1));
      if (trap)
      {
         traptrace();
         ic = 00001;
      }
      else
      {
         ic = addr;
      }
      break;

   case 0000100:   /* TZE */
      if (trap)
         traptrace();
      if ((ach & (Q|P|HMSK)) == 0 && acl == 0)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000114:   /* CVR */
   case 0000115:
   case 0000116:
   case 0000117:
      cvr();
      break;

   case 0000120:   /* TPL */
      if (trap)
         traptrace();
      if ((ach & SIGN) == 0)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000131:   /* XCA */
      srh = ach & (SIGN|HMSK);
      srl = acl;
      ach = mqh;
      acl = mql;
      mqh = srh;
      mql = srl;
      break;

   case 0000140:   /* TOV */
      if (trap)
         traptrace();
      if (acoflo != 0)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
         acoflo = 0;
      }
      break;

   case 0000161:   /* TQO */
      if (trap)
         traptrace();
      if (simulate && mqoflo != 0)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
         mqoflo = 0;
      }
      break;

   case 0000162:   /* TQP */
      if (trap)
         traptrace();
      if ((mqh & SIGN) == 0)
      {
         if (trap)
            ic = 00001;
         else
            ic = y;
      }
      break;

   case 0000200:   /* MPY */
      ACCESS(y);
      shcnt = 043;
      mpy();
      break;

   case 0000204:   /* VLM */
   case 0000205:   /* VLM (for 9M51B) */
      shcnt = ((srl & 000077000000) >> 18);
      ACCESS(y);
      if (shcnt)
         mpy();
      break;

   case 0000220:   /* DVH */
      ACCESS(y);
      shcnt = 043;
      div();
      if (divchk)
         run = 0;
      break;

   case 0000221:   /* DVP */
      ACCESS(y);
      shcnt = 043;
      div();
      break;

   case 0000224:   /* VDH */
      shcnt = ((srl & 000077000000) >> 18);
      ACCESS(y);
      if (shcnt)
      {
         div();
         if (divchk)
            run = 0;
      }
      break;

   case 0000225:   /* VDP */
   case 0000227:   /* VDP */
      shcnt = ((srl & 000077000000) >> 18);
      ACCESS(y);
      if (shcnt)
         div();
      break;

   case 0000240:   /* FDH */
      ACCESS(y);
      fdiv();
      if (divchk)
         run = 0;
      break;

   case 0000241:   /* FDP */
      ACCESS(y);
      fdiv();
      break;

   case 0000260:   /* FMP */
      ACCESS(y);
      fmpy(1);
      break;

   case 0000261:   /* DFMP */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      dfmpy(1);
      break;

   case 0000300:   /* FAD */
      ACCESS(y);
      fadd(1);
      break;

   case 0000301:   /* DFAD */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      dfadd(1);
      break;

   case 0000302:   /* FSB */
      ACCESS(y);
      srh ^= SIGN;
      fadd(1);
      break;

   case 0000303:   /* DFSB */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      srh ^= SIGN;
      dfadd(1);
      break;

   case 0000304:   /* FAM */
      ACCESS(y);
      srh &= ~SIGN;
      fadd(1);
      break;

   case 0000305:   /* DFAM */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      srh &= ~SIGN;
      dfadd(1);
      break;

   case 0000306:   /* FSM */
      ACCESS(y);
      srh |= SIGN;
      fadd(1);
      break;

   case 0000307:   /* DFSM */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      srh |= SIGN;
      dfadd(1);
      break;

   case 0000320:   /* ANS */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      srh = ach & srh;
      srl = acl & srl;
      if (srh & P)
         srh += SIGN - P;
      memh[y] = srh;
      setmeml(y, srl);
      CYCLE();
      break;

   case 0000322:   /* ERA */
      ACCESS(y);
      CYCLE();
      if (srh & SIGN)
         srh -= SIGN - P;
      ach = (ach ^ srh) & (P|HMSK);
      acl = acl ^ srl;
      if (srh & P)
         srh += SIGN - P;
      DCYCLE();
      break;

   case 0000340:   /* CAS */
      ACCESS(y);
      if ((ach & SIGN) == 0)
      {
         if ((srh & SIGN) == 0)
	 {
            if ( (ach & (Q|P|HMSK)) > (srh & HMSK) )
               goto skip0;
            if ( (ach & (Q|P|HMSK)) < (srh & HMSK) )
               goto skip2;
            if ( acl > srl )
               goto skip0;
            if ( acl < srl )
               goto skip2;
            goto skip1;
         }
	 else
	 {
            goto skip0;
         }
      }
      else
      {
         if ((srh & SIGN) == 0)
	 {
            goto skip2;
         }
	 else
	 {
            if ( (ach & (Q|P|HMSK)) > (srh & HMSK) )
               goto skip2;
            if ( (ach & (Q|P|HMSK)) < (srh & HMSK) )
               goto skip0;
            if ( acl > srl )
               goto skip2;
            if ( acl < srl )
               goto skip0;
            goto skip1;
         }
      }
skip2:ic++;
skip1:ic++;
skip0:break;

   case 0000361:   /* ACL */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      adderl = srl + acl;
      adderh = (srh & (P|HMSK)) + (ach & (P|HMSK));
      if (adderl < srl)
         adderh++;
      if (adderh & Q)
      {
         adderl++;
         if (adderl == 0)
            adderh++;
      }
      if (srh & P)
         srh += SIGN - P;
      acl = adderl;
      ach = (adderh & (P|HMSK)) | (ach & (SIGN|Q));
      CYCLE();
      break;

   case 0000400:   /* ADD */
      ACCESS(y);
      add();
      CYCLE();
      break;

   case 0000401:   /* ADM */
      ACCESS(y);
      srh &= ~SIGN;
      add();
      CYCLE();
      break;

   case 0000402:   /* SUB */
      ACCESS(y);
      srh ^= SIGN;
      add();
      CYCLE();
      break;

   case 0000420:   /* HPR */
      stop = 1;
      cycle_count++;
      addr = ic;
      ic--;
      break;

   case 0000440:   /* IIS */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      sih ^= srh;
      sil ^= srl;
      if (srh & P)
         srh += SIGN - P;
      break;

   case 0000441:   /* LDI */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      sih = srh;
      sil = srl;
      if (srh & P)
         srh += SIGN - P;
      break;

   case 0000442:   /* OSI */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      sih |= srh;
      sil |= srl;
      if (srh & P)
         srh += SIGN - P;
      break;

   case 0000443:   /* DLD */
      if (cpumode != 7094) goto ILLINST;
      ACCESS(y);
      ach = srh;
      acl = srl;
      ACCESS(y+1);
      mqh = srh;
      mql = srl;
           break;

   case 0000444:   /* OFT */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      if ( (srh & ~sih) == srh &&
           (srl & ~sil) == srl )
         ic++;
      if (srh & P)
         srh += SIGN - P;
      CYCLE();
      DCYCLE();
      break;

   case 0000445:   /* RIS */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      sih &= ~srh;
      sil &= ~srl;
      if (srh & P)
         srh += SIGN - P;
      break;

   case 0000446:   /* ONT */
      ACCESS(y);
      if (srh & SIGN)
         srh -= SIGN - P;
      if ( (srh & sih) == srh  &&
           (srl & sil) == srl )
         ic++;
      if (srh & P)
         srh += SIGN - P;
      CYCLE();
      DCYCLE();
      break;

   case 0000500:   /* CLA */
      ACCESS(y);
      ach = srh;
      acl = srl;
      break;

   case 0000502:   /* CLS */
      ACCESS(y);
      srh ^= SIGN;
      ach = srh;
      acl = srl;
      break;

   case 0000520:   /* ZET */
      ACCESS(y);
      if ((srh & HMSK) == 0 && srl == 0)
         ic++;
      break;

   case 0000534:   /* LXA */
      ACCESS(addr);
      setxr(srl);
      break;

   case 0000535:   /* LAC */
      ACCESS(addr);
      setxr(0100000 - (srl & 077777));
      break;

   case 0000540:   /* RCHA */
   case 0000541:   /* RCHC */
   case 0000542:   /* RCHE */
   case 0000543:   /* RCHG */
      chan = (op & 03) << 1;
#ifdef DEBUGIO
      fprintf (stderr,
	    "RCH Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + chan, ic, ctrap_enb, trap, channel[chan].ceof);
#endif
      CYCLE();
      channel[chan].ctrp = 0;
      channel[chan].cchk = 0;
      if (channel[chan].csel == READ_SEL || channel[chan].csel == WRITE_SEL)
      {
         channel[chan].clr = y;
         channel[chan].ceor = 0;
         load_chan(chan, 0);
      }
      else
      {
         iochk = 1;
#ifdef DEBUGIO
         fprintf (stderr, "RCH iochk\n");
#endif
      }
      break;

   case 0000544:   /* LCHA */
   case 0000545:   /* LCHC */
   case 0000546:   /* LCHE */
   case 0000547:   /* LCHG */
      chan = (op & 03) << 1;
#ifdef DEBUGIO
      fprintf (stderr,
	    "LCH Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + chan, ic, ctrap_enb, trap, channel[chan].ceof);
#endif
      CYCLE();
      if ((channel[chan].csel == READ_SEL || channel[chan].csel == WRITE_SEL)
	    && channel[chan].cact)
      {
         run_chan(chan);
         if (channel[chan].csel == READ_SEL || channel[chan].csel == WRITE_SEL)
	 {
            channel[chan].clr = y;
            load_chan(chan, 0);
         }
	 else
	 {
            iochk = 1;
#ifdef DEBUGIO
	    fprintf (stderr, "LCH iochk\n");
#endif
         }
      }
      else
      {
         iochk = 1;
#ifdef DEBUGIO
         fprintf (stderr, "LCH iochk\n");
#endif
      }
      break;

   case 0000560:   /* LDQ */
      ACCESS(y);
      mqh = srh;
      mql = srl;
      break;

   case 0000564:   /* ENB */
      ACCESS(y);
      ctrap_enb = srl & 00037700377;
      ctrap_ind = 1;
#ifdef DEBUGIO
      fprintf (stderr, "ENB ic = %05o, ctrap_enb = %o, trap = %d\n",
	       ic, ctrap_enb, trap);
#endif
      break;

   case 0000600:   /* STZ */
      memh[y] = 0;
      setmeml(y, 0L);
      CYCLE();
      break;

   case 0000601:   /* STO */
      memh[y] = ach & (SIGN|HMSK);
      setmeml(y, acl);
      CYCLE();
      break;

   case 0000602:   /* SLW */
      memh[y] = ((ach << 4) & SIGN) | (ach & HMSK);
      setmeml(y, acl);
      CYCLE();
      break;

   case 0000604:   /* STI */
      srh = sih;
      srl = sil;
      if (srh & P)
         srh += SIGN - P;
      memh[y] = srh;
      setmeml(y, srl);
      break;

   case 0000621:   /* STA */
      setmeml(y, (getmeml(y) & 037777700000) |
            (acl &     000000077777));
      CYCLE();
      break;

   case 0000622:   /* STD */
      memh[y] = (memh[y] & 0376) | (ach & 001);
      setmeml(y, (getmeml(y) & 000000777777) |
            (acl &     037777000000));
      CYCLE();
      break;

   case 0000625:   /* STT */
      setmeml(y, (getmeml(y) & 037777077777) |
            (acl &     000000700000));
      CYCLE();
      break;

   case 0000630:   /* STP */
      memh[y] = (memh[y] & 001) |
           ((ach << 4) & SIGN) | (ach & 006);
      CYCLE();
      break;

   case 0000634:   /* SXA */
      setmeml(addr, (getmeml(addr) & 037777700000) | getxr());
      CYCLE();
      break;

   case 0000636:   /* SCA */
      {
	 uint16 x = 0100000 - getxr() & 077777;
	 if (tag == 0) x = 0;
	 setmeml(addr, (getmeml(addr) & 037777700000) | x);
	 CYCLE();
      }
      break;

   case 0000640:   /* SCHA */
   case 0000641:   /* SCHC */
   case 0000642:   /* SCHE */
   case 0000643:   /* SCHG */
      chan = (op & 03) << 1;
#ifdef DEBUGIO
      fprintf (stderr,
	    "SCH Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + chan, ic, ctrap_enb, trap, channel[chan].ceof);
#endif
      CYCLE();
      srh = ((channel[chan].cop << 5) & SIGN) |
            ((channel[chan].cop << 1) & 06) |
            ((channel[chan].clr >> 14) & 1);
      srl = ((channel[chan].cop << 13) & 000000200000) |
            (((uint32)channel[chan].clr << 18) & 037777000000) |
             (channel[chan].car & 000000077777);
      setmeml(y, srl);
      memh[y] = srh;
      break;

   case 0000734:   /* PAX */
      setxr(acl);
      break;

   case 0000737:   /* PAC */
      setxr(0100000 - (acl & 077777));
      break;

   case 0000754:   /* PXA */
      ach = 0;
      acl = getxr();
      break;

   case 0000756:   /* PCA */
      ach = 0;
      if (tag != 0)
      {
         acl = (0100000 - getxr()) & 077777;
      }
      else
         acl = 0;
           break;

   case 0000761:   /* NOP */
      cycle_count++;
      break;

   case 0000762:   /* RDS */
      chan = (addr & 017000) >> 9;
#ifdef DEBUGIO
      fprintf (stderr,
"RDS Channel %c, ic = %05o, addr = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
      'A' + (chan-1), ic, addr & 077777, ctrap_enb, trap, channel[chan-1].ceof);
#endif
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         channel[chan].ceof = 0;
         if (unitcheck(chan, 1) != -1)
	 {
            channel[chan].ctrp = 0;
            channel[chan].csel = READ_SEL;
            startrec(chan);
         }
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "RDS MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   case 0000763:   /* LLS */
      for (y &= 0377; y; y--)
      {
         ach = (ach & SIGN) | ((ach << 1) & (Q|P|HMSK));
         if (acl & 020000000000)
            ach++;
         acl <<= 1;
         if (mqh & 04)
            acl++;
         mqh = (mqh & SIGN) | ((mqh << 1) & HMSK);
         if (mql & 020000000000)
            mqh++;
         mql <<= 1;
         if (ach & P)
            acoflo = 1;
      }
      ach = (mqh & SIGN) | (ach & (Q|P|HMSK));
      break;

   case 0000764:   /* BSR */
      chan = (addr & 017000) >> 9;
#ifdef DEBUGIO
      fprintf (stderr,
	    "BSR Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + (chan-1), ic, ctrap_enb, trap, channel[chan-1].ceof);
#endif
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         dev = unitcheck(chan, -1);
         if (dev != -1)
	 {
            channel[chan].csel = BSR_SEL;
            channel[chan].cact = 1;
            chan_in_op |= 1 << chan;
         }
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "BSR MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   case 0000765:   /* LRS */
      for (y &= 0377; y; y--)
      {
         mql >>= 1;
         if (mqh & 1)
            mql |= 020000000000;
         mqh = (mqh & SIGN) | ((mqh >> 1) & HMSK);
         if (acl & 1)
            mqh |= 04;
         acl >>= 1;
         if (ach & 1)
            acl |= 020000000000;
         ach = (ach & SIGN) | ((ach >> 1) & (Q|P|HMSK));
      }
      mqh = (ach & SIGN) | (mqh & HMSK);
      break;

   case 0000766:   /* WRS */
      chan = (addr & 017000) >> 9;
#ifdef DEBUGIO
      fprintf (stderr,
"WRS Channel %c, ic = %05o, addr = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	'A' + (chan-1), ic, addr & 077777, ctrap_enb, trap, channel[chan].ceof);
#endif
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         if (unitcheck(chan, 0) != -1)
	 {
            channel[chan].ctrp = 0;
            channel[chan].csel = WRITE_SEL;
            startrec(chan);
         }
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "WRS MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   case 0000767:   /* ALS */
      for (y &= 0377; y; y--)
      {
         ach = (ach & SIGN) | ((ach << 1) & (Q|P|HMSK));
         if (acl & 020000000000)
            ach++;
         acl <<= 1;
         if (ach & P)
            acoflo = 1;
      }
      break;

   case 0000770:   /* WEF */
      chan = (addr & 017000) >> 9;
#ifdef DEBUGIO
      fprintf (stderr,
	    "WEF Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + (chan-1), ic, ctrap_enb, trap, channel[chan-1].ceof);
#endif
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         dev = unitcheck(chan, 0);
         if (dev != -1)
	 {
            channel[chan].csel = WEF_SEL;
            channel[chan].cact = 1;
            chan_in_op |= 1 << chan;
         }
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "WEF MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   case 0000771:   /* ARS */
      for (y &= 0377; y; y--)
      {
         acl >>= 1;
         if (ach & 1)
            acl |= 020000000000;
         ach = (ach & SIGN) | ((ach >> 1) & (Q|P|HMSK));
      }
      break;

   case 0000772:   /* REW */
      chan = (addr & 017000) >> 9;
#ifdef DEBUGIO
      fprintf (stderr,
	    "REW Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + (chan-1), ic, ctrap_enb, trap, channel[chan-1].ceof);
#endif
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         dev = unitcheck(chan, -1);
         if (dev != -1)
	 {
            dorewind(dev);
         }
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "REW MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   case 0000774:   /* AXT */
      setxr(srl);
      break;

   case 0000776:   /* SDN */
      chan = (addr & 017000) >> 9;
      if (chan && chan <= NUMCHAN)
      {
         chan--;
         if (channel[chan].cact)
            do_chan(chan);
         channel[chan].cunit = (addr - getxr()) & 0777;
         dev = unitcheck(chan, -1);
      }
      else
      {
         machchk = 1;
         sprintf (errview[0], "SDN MACHINE check: chan = %o\n",
		  chan);
         run = 0;
      }
      CYCLE();
      break;

   default:
ILLINST:
      machchk = 1;
      sprintf (errview[0], "Illegal instruction: op = %o\n", op);
      run = 0;
      break;
   }
}

void
cvr()
{
   uint32 i;

   srl = (srl & 037777700000) | addr;
   shcnt = ((srl & 000377000000) >> 18);
   while (shcnt)
   {
      i = (srl + (acl & 077)) & 077777;
      ACCESS(i);
      for (i = 0; i < 6; i++)
      {
         acl >>= 1;
         if (ach & 1)
            acl |= 020000000000;
         ach = (ach & SIGN) | ((ach >> 1) & (P|HMSK));
      }
      if (srh & SIGN)
         srh -= SIGN - P;
      ach |= srh;
      acl |= srl & 030000000000;
      shcnt--;
   }
   tag &= 1;
   if (tag)
      setxr(srl);
}
