/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 13-Dec-85 | [1.183] Created
* 14-Dec-85 | [1.188] Created from SAR.C
* 30-Dec-85 | [1.281] Tell_op includes op_B
* 27-Jan-86 | [1.350] declare single_cycle_decode
* 25-Feb-86 | [1.379] include <> => include ""
*  6-Aug-86 | [1.410] 'bytes' array now unsigned char
* 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_SBR false

/* Machine State:    */

#define SBR_B_1_complete single_cycle(i_SBR,local_microstate+1)
#define SBR_B_2_complete single_cycle(i_SBR,local_microstate+2)
#define SBR_B_3_complete single_cycle(i_SBR,local_microstate+3)
	
static unsigned char bytes[3];	/* The converted address */

extern char * single_cycle_decode();

/*****************************************************************************
				1401 Simulator

			       Store B-Register


			 Store B-Register (One Address)
			 ------------------------------
Instruction format

Mnemonic	Op Code	A-address
--------        ------- ---------
SBR		H	AAA		

Function: This instruction stores the contents of the B-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		Bp

Chaining:  This instruction can be chained to the previous instruction
if that instruction left valid address register contents by supplying
only the opcode.

*****************************************************************************/


/****************************************************************************
*                                   inst_SBR
* 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_SBR()
    {
     int i;

     tell_op(op_A|op_B);
     switch(I_cycle)
        { /* length decode */
	 case 1:	/* chained */
	 case 4:	/* one-address */
	 case 7:	/* two-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
		*/
	 	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_SBR
		    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 = SBR_B_1_complete;
		A_addr--;
		cycle = cycle_A;
		break;
	 case SBR_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 = SBR_B_2_complete;
		A_addr--;
		cycle = cycle_A;
		break;
	 case SBR_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("SBR");
     return true;
    }
