/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 25-Nov-85 | [1.131] Created
*  8-Dec-85 | [1.157] Set single_cycle_complete at end of run decode
* 13-Dec-85 | [1.181] created from mlcwa
* 27-Jan-86 | [1.350] declare single_cycle_decode()
* 25-Feb-86 | [1.379] include <> => include ""
* 10-Nov-91 | [1.428] <jmn> converted to Microsoft C 6.0 libraries
* 18-Nov-91 | [1.428] <jmn> memory.h => mem1401.h, avoid ANSI name
*****************************************************************************/

#include "stdio.h"
#include "btypes.h"
#include "mem1401.h"
#include "boolean.h"
#include "mach.h"
#include "diag.h"
#include "instr.h"

/* Machine State:    */
#define MRCM_last (local_microstate+1)

#define MRCM_A_complete single_cycle(i_MRCM,A_complete)
#define MRCM_B_complete single_cycle(i_MRCM,B_complete)
#define MRCM_A_last     single_cycle(i_MRCM,MRCM_last)
	
#define record_mark 032
#define GMWM        (077|word_mark)
	
extern char * single_cycle_decode();

/*****************************************************************************
				1401 Simulator

				  Move Record
		    (Move Right Characters to record mark)


		Move Characters to Record Mark (Two Addresses)
		----------------------------------------------

Instruction format

Mnemonic	Op Code	A-address	B-address
--------        ------- ---------       ---------
MRCM		P	AAA		BBB

Function: This instruction makes it possible to move an entire record
from one core storage are to another, regardless of the presence of
word marks in either field.  The A- and B-addresses specify the
high-order position of the respective areas.  Transmission starts from
the high-order addresses and continues until a record mark (A82 bits)
or a group mark with a word mark (BA8421M) is sensed in the A-field.
The record mark or group mark transfers to the B-field.

Word Marks:  Word marks within the area to not affect the operation.
Word marks in the B-field are unchanged.  A field word marks are not
transmitted to the B-field.

Address Registers After Operation:

I-Add		A-Add		B-Add
-----		-----		-----
NSI		A+La		B+La

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_MRCM
* result: boolean
*	true if instruction succeeded
*	false if instruction failed
* Effect: 
*	Executes move record instruction
****************************************************************************/

boolean inst_MRCM()
    {
     boolean quit;
     boolean result;
     boolean cycling;

     tell_op(op_A|op_B);

      result = true;
      cycling = true;
      quit = false;

      while(cycling)
         { /* move chars */
	  if(bad_address_r(A_addr))
	     { /* bogus */
	      cycle = cycle_A;
	      result = false;
	      quit = true;
	      cycling = false;
	      break;
	     } /* bogus */

	  if(bad_address_r(B_addr))
	     { /* bogus */
	      cycle = cycle_B;
	      result = false;
	      quit = true;
	      cycling = false;
	      break;
	     } /* bogus */
	      
	  switch(single_cycle_state)
	     { /* state decode */
	      case single_cycle_run:
	      		B = BA8421(memory[A_addr]);
	      		A = memory[B_addr] = B | WM(memory[B_addr]);
			quit = BA8421(memory[A_addr]) == record_mark ||
				memory[A_addr] == GMWM;
			A_addr++;
			B_addr++;
			break;
	      case MRCM_B_complete:
	      case single_cycle_start:
	      		B = memory[A_addr];
			A_addr++;
			cycle = cycle_A;
			single_cycle_state = ( BA8421(B) == record_mark ||
						B == GMWM
						? MRCM_A_last : MRCM_A_complete);
			cycling = false;
			break;
	      case MRCM_A_complete:
	      		A = B;
			memory[B_addr] = BA8421(A) | WM(memory[B_addr]);
			B_addr++;
			cycle = cycle_B;
			single_cycle_state = MRCM_B_complete;
			cycling = false;
			break;
	      case MRCM_A_last:
	      		A = B;
			memory[B_addr] = BA8421(A) | WM(memory[B_addr]);
			B_addr++;
			cycle = cycle_B;
			single_cycle_state = MRCM_B_complete;
			cycling = false;
			quit = true;
			break;
	      default:
	      		sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode());
			tell(diag_buffer);
			result = false;
			cycling = false;
			break;
	     } /* state decode */

	      if(quit) 
	      	{
		 single_cycle_state = single_cycle_complete;
		 break;
		}
 	  
	 } /* move chars */
	  
      tell_new_state("MRCM");
      return result;	
    }
