
/**
   COPYRIGHT (C) 2007 Jonathan Grothe
   All Rights Reserved
   Instances of this class represent the processor of a simulated computer.
   @author Jonathan Grothe
   @version 1.0 2009/2/2
 */
public class Processor
{	
	/**
	   Constructs a new Processor object.
	*/
	public Processor()
	{	pc = 0;
		IR = 0;
		cell = null;
		reg = new int[8];
	}
	
	/**
	   Sets cell equal to the memory.
	   @param mSet = Memory to set cell equal to.
	*/
	public void setMemory(Memory mSet)
	{	cell = mSet;
	}
	
	/**
	   Sets the program counter to iSet.
	   @param iSet = New program counter.
	*/
	public void setPC(int iSet)
	{	pc = iSet;
	}
		
	/**
	   Executes the next step given in the register.
	   @return boolean value representing if the halt command was given.
	*/
	public boolean step()
	{	boolean bHlt = false;
		int iCmd=mask(8);
		int a=mask(4);
		int b=mask(0);
		
		switch (iCmd) 
    	{  	case 0x1: reg[a] = cell.get(reg[b]);  break;		//load a b
            case 0x2: reg[a] = cell.get(++pc);    break;		//loadc a
            case 0x3: cell.write(reg[a], reg[b]); break;		//store a b
            case 0x4: reg[a] = reg[a] + reg[b];   break;		//add a b
            case 0x5: reg[a] = reg[a] * reg[b];   break;		//mul a b
            case 0x6: reg[a] = reg[a] - reg[b];   break;		//sub a b
            case 0x7: div(a, b); 				  break;		//div a b
            case 0x8: if(reg[a]!=0 && reg[b]!=0) reg[a]=1;
            		  else reg[a] = 0;			  break;		//and a b
            case 0x9: if(reg[a]!=0 || reg[b]!=0) reg[a]=1;
            		  else reg[a] = 0;			  break;		//or a b
            case 0xa: if(reg[b]!=0) reg[a]=0; 
            		  else reg[a] = 1;			  break;		//not a b
            case 0xb: reg[a] = reg[b] << 1;		  break;		//lshift a b
            case 0xc: reg[a] = reg[b] >> 1;		  break;		//rshift a b
            case 0xd: reg[a] = reg[a] & reg[b];   break;		//bwc a b
            case 0xe: reg[a] = reg[a] | reg[b];   break;		//bwd a b
            case 0xf: if(reg[a]!=0) pc = reg[b];  break;		//if a b
        	default: if(iCmd==0x0) bHlt = true;   break;		//hault
		}
		pc++;
		return bHlt;
	}

	private void div(int a, int b)
	{	if(reg[b]!=0)
			reg[a] = reg[a] / reg[b];			
	}
	
	private int mask(int iSh)
	{	int iRet = cell.get(pc)>>iSh;
		return iRet & 0xf;
	}
	
	/**
	   Outputs PC, IR, and the value stored in each register.
	*/
	public void dump()
	{	System.out.println("Registers:");
		for(int x=0; x<reg.length; x++)
			System.out.println("reg[" + Integer.toHexString(x) +"] = " + Integer.toHexString(reg[x]));
		System.out.println("PC = " + pc);
		System.out.println("IR = " + IR);
	}
	
	private int pc;
	private int IR;
	private Memory cell;
	private int[] reg;
}