/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 16-Nov-85 | [1.80] Created
* 26-Nov-85 | [1.150] Updated to support single cycle
*  8-Dec-85 | [1.157] Set state to single_cycle_complete at the end of each
*           | run state completion.
*           | Add default case decode error trap
*  8-Dec-85 | [1.162] Created from SW.C
* 12-Dec-85 | [1.172] created mlns from mlzs
* 25-Jan-86 | [1.327] Check for bad instr length
* 25-Feb-86 | [1.379] include <> => include ""
* 31-Jul-86 | [1.405] Make char unsigned
* 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 "mem1401.h"
#include "btypes.h"
#include "boolean.h"
#include "mach.h"
#include "diag.h"
#include "instr.h"
#include "alerts.h"
#include "ifetch.h"
#include "alert.h"

/* Machine State:	*/

#define MLNS_A_f_complete single_cycle(i_MLNS,A_f_complete)
#define MLNS_A_s_complete single_cycle(i_MLNS,A_s_complete)
#define MLNS_B_f_complete single_cycle(i_MLNS,B_f_complete)
#define MLNS_B_s_complete single_cycle(i_MLNS,B_s_complete)

/*****************************************************************************
				1401 Simulator

		     Move Left Numeric Single Instruction


		   Move Left Numeric Single (Two Addresses)
		   ----------------------------------------

Instruction format

Mnemonic	Op Code	A-address	B-address
--------        ------- ---------       ---------
MLNS		D	AAA		BBB

Function: Only the numeric portion (8421-bits) is moved from the A-address to
the B-address.  The zone portion (BA-bits) is not disturbed at either
location.

Word Marks:  Word marks are not required at either location, because this
instruction involves a single character.  Word marks in either field are
undisturbed.


Address Registers After Operation:

I-Add		A-Add		B-Add
NSI		A-1		B-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.


		    Move Left Numeric Single (One Address)
		    --------------------------------------
Instruction format

Mnemonic	Op Code	A-address
--------        ------- ---------
MLNS		D	AAA		

Function: Not very interesting; the numeric bits are moved from the A-field to
the A-field

Word Marks:  Word marks are not required at the location, because this
instruction involves a single character.  Word marks in either field are
undisturbed.


Address Registers After Operation:

I-Add		A-Add		B-Add
-----           -----           -----
NSI		A-1		A-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_MLNS
* result: boolean
*	true if instruction succeeded
*	false if instruction failed
* Effect: 
*	Executes move-left-numeric-single instruction
****************************************************************************/

boolean inst_MLNS()
    {
     unsigned char to;

     tell_op(op_A|op_B);

     switch(I_cycle)
         {
	  case 1: /* chained */
	  case 4: /* one-address */
	  case 7: /* two-address */
	  	break;
	  default: /* Illegal length */
	  	illegal_length();
	  	return false;
	 }

     if(bad_address(A_addr)) 
     	{ /* bogus A */
	 cycle = cycle_A;
	 return false;
	} /* bogus A */

     if(bad_address(B_addr))
     	{ /* bogus A */
	 cycle = cycle_B;
	 return false;
	} /* bogus A */

     switch(I_cycle)
         {
	  case 1: /* chained */
	  case 4: /* one-address */
	  case 7: /* two-address */
		break;
	  default: /* Illegal length */
	  	illegal_length();
	  	return false;
	 }

/*
	States:
		single_cycle_start:	
				fetch character from A
				=> A_f_complete
		A_f_complete:	
				Fetch character from B-field 
				=> B_f_complete
		B_f_complete:	
				Form new character in B and store into B-field
				=> complete
*/

      switch(single_cycle_state)
         { /* state decode */
	  case single_cycle_run:
	  	to = memory[B_addr];
		A = memory[A_addr];
	  	B = ZONEBITS(to) | WM(to) | NUMBITS(A);
		memory[B_addr] = B;
		A_addr--;
		B_addr--;
		single_cycle_state = single_cycle_complete;
		break;
	  case single_cycle_start:
	  	B = A = memory[A_addr];
		cycle = cycle_A;
		single_cycle_state = MLNS_A_f_complete;
		A_addr--;
		break;
	  case MLNS_A_f_complete:
	  	B = memory[B_addr];
		cycle = cycle_B;
		single_cycle_state = MLNS_B_f_complete;
		break;
	  case MLNS_B_f_complete:
	  	B = ZONEBITS(B) | WM(B) | NUMBITS(A);
		memory[B_addr] = B;
		cycle = cycle_B;
		single_cycle_state = single_cycle_complete;
		B_addr--;
		break;
	  default:
		   { /* error */
		    tell("Bad instruction microstate decode---MLNS");
		    alert(alert_process);
		    tell_new_state("MLNS");
		    return false;
		   } /* error */
		    
	 } /* state decode */

      tell_new_state("MLNS");
      return true;	
    }
