/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 24-Nov-85 | [1.105] Created
* 12-Dec-85 | [1.174] Added single-cycle code
* 27-Jan-86 | [1.350] declare single_cycle_decode()
* 25-Feb-86 | [1.379] include <> => include ""
* 30-Jul-86 | [1.403] Fixed bug where CS A style instruction looped infinitely
*           | in single cycle or addr stop modes
* 10-Nov-91 | [1.428] <jmn> converted to Microsoft C 6.0
* 18-Nov-91 | [1.428] <jmn> memory.h => mem1401.h, avoid ANSI name
*****************************************************************************/

#include "stdio.h"
#include "boolean.h"

#include "btypes.h"
#include "mem1401.h"

#include "mach.h"
#include "diag.h"
#include "instr.h"
#include "ifetch.h"
#include "poll.h"

/* Machine State */

#define CS_A_complete single_cycle(i_CS,A_complete)

extern char * single_cycle_decode();

/*****************************************************************************
				1401 Simulator

			   Clear Storage Instruction


			 Clear Storage (Two Addresses)
			 -----------------------------

Instruction format

Mnemonic	Op Code	I-address	B-address
--------        ------- ---------       ---------
CS		/	III		BBB

Function: This is the same as the Clear Storage instruction, except that
the clearing starts at the B-address.  The I-address specifies the location
of the next instruction.

Word Marks:  Word marks are not required to stop the operation.  It is
not necessary to follow this instruction by a character with a word mark.

Address Registers After Operation:

I-Add		A-Add		B-Add
NSI		BI		NSI

Chaining: 


			 Clear Storage (One Address)
			 ---------------------------
Instruction format

Mnemonic	Op Code	A-address
--------        ------- ---------
CS		/	AAA		

Function: As many as 100 positions of core storage can be cleared of data
and word marks when this instruction is executed.  Clearing starts at
the A-address and continues  leftward to the nearest hundreds position.
The cleared area is set to blanks.

Word Marks:  A word mark is not required to stop the operation.  Word marks
in the affected storage locations are removed.

Note: During the execution of this instruction only the B-address register is
used.  Therefore, when chaining is begin considered, the contents of the
A-address register can be ignored.

If the last location cleared is location 000, the memory wraps to the highest
physical memory location (15999 in a 16K machine).

Address Registers After Operation:

I-Add		A-Add		B-Add
-----           -----           -----
NSI		A		x00-1

Chaining: This instruction can be chained to the preceding operation (if
that instruction left usable address-register contents) by supplying
only the operation code.


*****************************************************************************/


/****************************************************************************
*                                   inst_CS
* result: boolean
*	true if instruction succeeded
*	false if instruction failed
* Effect: 
*	Executes clear-storage instruction
****************************************************************************/

boolean inst_CS()
    {
     int i;

     tell_op(op_A|op_B);

     switch(I_cycle)
         {
	  case 1: /* chained */
		break;
	  case 4: /* one-address */
#if 0

/* Redundant since single-address instr loads both A and B */
	  	switch(single_cycle_state)
		   { /* states */
		    case single_cycle_run:
		    case single_cycle_start:
		    			B_addr = A_addr;
					break;
		    default:
		    	break;
		   } /* states */
#endif
		break;
	  case 7: /* two-address */
		NI_addr = A_addr;
		poll();
		break;
	  default: /* Illegal */
	  	illegal_length();
	  	return false;
	 }

      /* If we get here, we are ready to clear storage.  B_addr is our
         start position */

      switch(single_cycle_state)
         { /* state decode */
	  case single_cycle_run:
	  	for(i=B_addr;i >= (B_addr - B_addr % 100);i--)
		   { /* clear it */
		    memory[i] = '\0';	/* bcd space */
		   } /* clear it */
		B_addr = i;
		B = '\0';	/* for display */
		break;
	  case single_cycle_start:
	  case CS_A_complete:
	  	B = '\0';	/* space to store (for display) */
		memory[B_addr] = '\0';
		if(B_addr % 100 == 0)
		   { /* done */
		    cycle = cycle_B;
		    single_cycle_state = single_cycle_complete;
		   } /* done */
		else
		   { /* more to do */
		    single_cycle_state = CS_A_complete;
		    cycle = cycle_B;
		   } /* more to do */
		B_addr--;
	  	break;
	  default:
	  	sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode());
		tell(diag_buffer);
		single_cycle_state = single_cycle_complete;
		break;
	 } /* state decode */

      if(B_addr < 0) B_addr = 15999;

      tell_new_state("CS");
      return true;	
    }
