/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 13-Dec-85 | [1.183] Created
* 27-Jan-86 | [1.350] declare single_cycle_decode
* 25-Feb-86 | [1.379] include <> => include ""
*  6-Aug-86 | [1.410] 'bytes' array is now unsigned
* 10-Nov-91 | [1.428] <jmn> converted for Microsoft C 6.0
* 18-Nov-91 | [1.428] <jmn> memory.h => mem1401.h, avoid ANSI name
*****************************************************************************/

#include "stdio.h"
#include "btypes.h"
#include "boolean.h"
#include "mem1401.h"
#include "mach.h"
#include "diag.h"
#include "instr.h"
#include "ifetch.h"
#include "cvbytes.h"

#define debug_SAR false

/* Machine State:    */

#define SAR_B_1_complete single_cycle(i_SAR,local_microstate+1)
#define SAR_B_2_complete single_cycle(i_SAR,local_microstate+2)
#define SAR_B_3_complete single_cycle(i_SAR,local_microstate+3)
	
static unsigned char bytes[3];	/* The converted address */

extern char * single_cycle_decode();

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

			       Store A-Register


			 Store A-Register (One Address)
			 ------------------------------
Instruction format

Mnemonic	Op Code	A-address
--------        ------- ---------
SAR		Q	AAA		

Function: This instruction stores the contents of the A-address register from
the previous operation in the 3-position field that has its units position
defined by the A-address of the Store A-Address-Register instruction.

Word Marks: Word marks are not affected.

Address Registers After Operation:

I-Add		A-Add		B-Add
-----           -----           -----
NSI		A-3		Ap

Chaining:  If this instruction is chained (operation code only) to the
preceding operation, the following will result (assume xxx is 1-char
field)

		        Registers after
			/              \
	Instruction	A-addr	B-addr  zzz    zzz-3
	-----------	------	------  ---    -----
	M xxx yyy	xxx-1	yyy-1	???	???
	Q zzz		zzz-3	xxx-1   xxx-1	???
	Q		zzz-6	zzz-3   xxx-1	zzz-3
*****************************************************************************/


/****************************************************************************
*                                   inst_SAR
* result: boolean
*	true if instruction succeeded
*	false if instruction failed
* Effect: 
*	Stores the previous A-address in the field designated by the
*	A-address of this instruction.
****************************************************************************/

boolean inst_SAR()
    {
     int i;

     tell_op(op_A);
     switch(I_cycle)
        { /* length decode */
	 case 1:	/* chained */
	 case 4:	/* one-address */
	 	break;
	 default:
	 	illegal_length();
		return false;
	} /* length decode */
     switch(single_cycle_state)
        { /* state decode */
	 case single_cycle_run:
	 	/* Note that we cannot convert it directly into memory because
		   wordmarks at destination site must be preserved

		   We store the contents of the B_addr register because the
		   instruction fetch logic set B = Ap.
		*/
	 	cvbytes(bytes,B_addr);
		for(i=2;i>=0;i--)
		   { /* store it */
		    if(bad_address(A_addr-2+i))
		       { /* can't store */
		        cycle = cycle_A;
			return false;
		       } /* can't store */
#if debug_SAR
		    if(diagnostics_on)
		       { /* tell */
			sprintf(diag_buffer,"%d:memory[%d] = %c",
		    				i,A_addr-2+i,bcd_to_ascii(bytes[i]));
		        tell(diag_buffer);
		       } /* tell */
#endif
		    B = memory[A_addr-2+i] = bytes[i] | WM(memory[A_addr-2+i]);
		   } /* store it */
		A_addr -= 3;
		single_cycle_state = single_cycle_complete;
		break;
	 case single_cycle_start:
	 	cvbytes(bytes,B_addr);	/* see note above */
		    if(bad_address(A_addr))
		       { /* can't store */
		        cycle = cycle_A;
			return false;
		       } /* can't store */
		B = memory[A_addr] = bytes[2];
		single_cycle_state = SAR_B_1_complete;
		A_addr--;
		cycle = cycle_A;
		break;
	 case SAR_B_1_complete:
		if(bad_address(A_addr))
		   { /* can't store */
		    cycle = cycle_A;
		    return false;
		   } /* can't store */
		B = memory[A_addr] = bytes[1];
		single_cycle_state = SAR_B_2_complete;
		A_addr--;
		cycle = cycle_A;
		break;
	 case SAR_B_2_complete:
		if(bad_address(A_addr))
		   { /* can't store */
		    cycle = cycle_A;
		    return false;
		   } /* can't store */
		B = memory[A_addr] = bytes[0];
		single_cycle_state = single_cycle_complete;
		cycle = cycle_A;
		A_addr--;
		break;
	default:
		sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode());
		tell(diag_buffer);
		return false;
		break;

	} /* state decode */
	 
     tell_new_state("SAR");
     return true;
    }
