/***********************************************************************
*
* sense.c - IBM 7090 emulator sense opcode routines.
*
* Changes:
*   ??/??/??   PRP   Original.
*   01/20/05   DGP   Changes for correct channel operation.
*   01/28/05   DGP   Revamped channel and tape controls.
*   
***********************************************************************/

#define EXTERN extern

#include <stdio.h>

#include "sysdef.h"
#include "regs.h"
#include "arith.h"

extern char errview[5][81];

void
sense_instr()
{
   uint32 select;

   switch (y)
   {

   case 00000:   /* CLM */
      ach = ach & SIGN;
      acl = 0;
      break;

   case 00001:   /* LBT/PBT */
      if ((op & 0100000) == 0)
      {
         if (acl & 00000000001)
            ic++;
      }
      else
      {
         if (ach & P)
            ic++;
      }
      break;

   case 00002:   /* CHS */
      ach = (~ach & SIGN) | (ach & (Q|P|HMSK));
      break;

   case 00003:   /* SSP/SSM */
      if ((op & 0100000) == 0)
      {
         ach = ach & (Q|P|HMSK);
      }
      else
      {
         ach = ach | SIGN;
      }
      break;

   case 00004:   /* ENK */
      mqh = kyh;
      mql = kyl;
      break;

   case 00005:   /* IOT */
      if (iochk)
         iochk = 0;
      else
         ic++;
      break;

   case 00006:   /* COM */
      ach = (ach & SIGN) | (~ach & (Q|P|HMSK));
      acl = ~acl;
      break;

   case 00007:   /* ETM/LTM */
      trap = 1 - (op >> 15);
      break;

   case 00010:   /* RND */
      rnd();
      break;

   case 00011:   /* FRN */
      frnd();
      break;

   case 00012:   /* DCT */
      if (divchk)
         divchk = 0;
      else
         ic++;
      break;

   case 00014:   /* RCT */
      ctrap_ind = 1;
      break;

   case 00016:   /* LMTM/EMTM */
      if (cpumode != 7094) goto ILLINST;
      multtag = op >> 15;
      break;

   case 00140:   /* SLF */
      sl = 0;
      break;

   case 00141:   /* SLN */
   case 00142:
   case 00143:
   case 00144:
      select = 1 << (0144 - y);
      if ((op & 0100000) == 0)
      {
         sl |= select;
      }
      else
      {
         if (sl & select)
	 {
            sl -= select;
            ic++;
         }
      }
      break;

   case 00161:   /* SWT */
   case 00162:
   case 00163:
   case 00164:
   case 00165:
   case 00166:
      if (ssw & (1 << (0166 - y)))
         ic++;
      break;

   case 01000:   /* BTT/ETT */
   case 02000:
   case 03000:
   case 04000:
   case 05000:
   case 06000:
   case 07000:
   case 10000:
      select = ((y & 00017000) >> 9) - 1;
#ifdef DEBUGIO
      fprintf (stderr,
	 "[BE]TT Channel %c, ic = %05o, ctrap_enb = %o, trap = %d, eof = %d\n",
	       'A' + select, ic, ctrap_enb, trap, channel[select].ceof);
#endif
      if (select >= NUMCHAN)
      {
         machchk = 1;
         run = 0;
         sprintf (errview[0],
		  "Sense MACHINE check: select = %o\n",
		  select);
         break;
      }
      if ((op & 0100000) == 0)
      {
         if (!channel[select].cbot)
            ic++;
         else
            channel[select].cbot = 0;
      }
      else
      {
         if (!channel[select].ceot)
            ic++;
         else
            channel[select].ceot = 0;
      }
      break;

   default:
      if ((y & 00700) == 00300)   /* SPR, SPT, SPU */
      {
         break;
      }
      break;            /* All others NOP */
   }
   return;

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