/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 15-Dec-85 | [1.200] Created
* 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
* 18-Nov-91 | [1.428] <jmn> memory.h => mem1401.h, avoid ANSI name
*****************************************************************************/
#include "mem1401.h"
#include "btypes.h"
#include "boolean.h"
#include "stdio.h"
#include "mach.h"
#include "diag.h"
#include "instr.h"
#include "alerts.h"
#include "ifetch.h"
#include "poll.h"

#define BBE_B_f_complete single_cycle(i_BBE,B_f_complete)

extern char * single_cycle_decode();

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

			Branch on Bit Equal Instruction


			      Branch on Bit Equal
			      -------------------

Instruction format

Mnemonic	Op Code	I-address	B-address	d-char
--------        ------- ---------       ---------	------
BBE		W	III		BBB		d

Function: The d-character can contain any character or any combination of
bits (BA8421) that can exist in a single position of core storage.  If the
character at the B-address contains any bit that matches any bit in the
d-character, the program branches to the I-address; otherwise, the
program continues normally.

Word Marks:  Word marks in the location tested have no effect on the
operation.

Address Registers After Operation:

No Branch:

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

Branch

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

Chaining: The instruction can be chained to the preceding operation by
supplying only the operation code.

*****************************************************************************/

/****************************************************************************
*                                   inst_BBE
* Result: boolean
*       true if processing should continue
*	false if processing should halt
* Effect: 
*       Executes the branch-on-word-or-zone instruction
****************************************************************************/

boolean inst_BBE()
    {

     tell_op(op_A|op_B|op_d);

     switch(I_cycle)
         {

/* W */
	  case 1: /* chained */

		if(bad_address(B_addr)) return false;

		switch(single_cycle_state)
		   { /* state decode */
		    case single_cycle_run:
		    	B = memory[B_addr];

			if(BA8421(B) & d_char)
			   { /* take branch */
			    NI_addr = A_addr;
			    B_addr = I_addr;
			    poll();
			   } /* take branch */
			else
			   { /* don't branch */
			    B_addr--;
			   } /* don't branch */
			single_cycle_state = single_cycle_complete;
			break;
		    case single_cycle_start:
		    	B = memory[B_addr];
			B_addr--;
			cycle = cycle_B;
			single_cycle_state = BBE_B_f_complete;
			break;
		    case BBE_B_f_complete:
			if(BA8421(B) &d_char)
			   { /* take branch */
			    NI_addr = A_addr;
			    B_addr = I_addr;
			    poll();
			   } /* take branch */
		        single_cycle_state = single_cycle_complete;
		    default:
			  sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode());
			  tell(diag_buffer);
			  single_cycle_state = single_cycle_complete;
		   } /* state decode */
		tell_new_state("BBE");
		break;

/* Wiiibbbd */
	  case 8: /* two-address + d */

		if(bad_address(B_addr)) return false;

		switch(single_cycle_state)
		   { /* state decode */
		    case single_cycle_run:
		    	B = memory[B_addr];

			if(BA8421(B) & d_char)
			   { /* take branch */
			    NI_addr = A_addr;
			    B_addr = I_addr;
			    poll();
			   } /* take branch */
			else
			   { /* don't branch */
			    B_addr--;
			   } /* don't branch */
			single_cycle_state = single_cycle_complete;
			break;
		    case single_cycle_start:
		    	B = memory[B_addr];
			A = d_char;	/* this may not be right... */
			B_addr--;
			cycle = cycle_B;
			single_cycle_state = BBE_B_f_complete;
			break;
		    case BBE_B_f_complete:
			if(BA8421(B) & d_char)
			   { /* take branch */
			    NI_addr = A_addr;
			    B_addr = I_addr;
			    poll();
			   } /* take branch */
		        single_cycle_state = single_cycle_complete;
		   } /* state decode */

		/* be sure to reset any indicators as described in 'notes' */
		single_cycle_state = single_cycle_complete;
		tell_new_state("BBE");
		break;
	  default: /* Illegal */
	  	illegal_length();
	  	return false;
	 }

      return true;
    }
