// It is important to note that these functions truncate
// the double to 32 bits before sign operations take place
//
// I have attempted to keep computation as close to the C
// implementation as possible
// 
// These functions are no longer referenced in the
// simulator behavioural files, but could be used in
// future projects using strings

//==========================
//Methods to accept ints as well as doubles
//==========================

public static int BitOp(int a, double b, char op){
	double c = (new Integer(a)).doubleValue();
	return(BitOp(c,b,op));
}

public static int BitOp(double a, int b, char op){
	double c = (new Integer(b)).doubleValue();
	return(BitOp(a,c,op));

}

public static int BitOp(int a, int b, char op){
	double c = (new Integer(a)).doubleValue();
	double d = (new Integer(b)).doubleValue();
	return(BitOp(c,d,op));
}

public static int BitShiftRight(int a, int shift){
	double c = (new Integer(a)).doubleValue();
	return(BitShiftRight(c,shift));
}

public static int BitShiftLeft(int a, int shift){
	double c = (new Integer(a)).doubleValue();
	return(BitShiftLeft(c,shift));
}

//==========================
//AND (&), OR(|), XOR(^)
//==========================

public static int BitOp(double a, double b, char op){
	//convert the doubles to bitstrings
	String str1 = java.lang.Long.toBinaryString((new Double(a)).longValue());
	String str2 = java.lang.Long.toBinaryString((new Double(b)).longValue());

	int max1 = str1.length()-1;
	int max2 = str2.length()-1;
	int x = 0;
	int max = 0;
	boolean str1big = false;

	if (max1>max2){ max = max1; str1big = true; } else { max = max2; }

	//initialise the result character array	
	char result[] = new char[32];
	for(int z=0;z<32;z++) result[z]= '0';

	//both strings apply in the computation
	for(;x<=max1 && x<=max2 && x<32;x++){
		switch(op){
			//bitwise AND
			case '&': if(str1.charAt(max1-x) == '1' && str2.charAt(max2-x) == '1') result[31-x] = '1'; break;
					  //bitwise OR
			case '|': if(str1.charAt(max1-x) == '1' ||  str2.charAt(max2-x) == '1') result[31-x] = '1'; break;
					  //bitwise XOR
			case '^': if(str1.charAt(max1-x) == '0' &&  str2.charAt(max2-x) == '0') result[31-x] = '1'; break;
		}		  
	}

	//only one string applies in the computation
	for(;x<=max && x<32;x++){
		switch(op){
			//bitwise AND will always be 0 here, no arith required
			//bitwise OR
			case '|': if(str1big) {
					  if(str1.charAt(max1-x) == '1') result[31-x] = '1';
				  } else {
					  if(str2.charAt(max2-x) == '1') result[31-x] = '1';
				  } break;
				  //bitwise XOR
			case '^': if(str1big) {
					  if(str1.charAt(max1-x) == '0') result[31-x] = '1';
				  } else {
					  if(str2.charAt(max2-x) == '0') result[31-x] = '1';
				  } break;
		}		  
	}


	String str3 = new String(result);
	int ret = (java.lang.Long.valueOf(str3,2)).intValue();
	//System.out.println(str1);
	//System.out.println(str2);
	//System.out.println(str3);
	//System.out.println(ret);
	return ret;
}	

//==========================
//NEGATE (~a), note only 32 bits though
//==========================

public static int BitComplement(double a){
	//convert the double to a bitstring
	String str1 = java.lang.Long.toBinaryString((new Double(a)).longValue());

	int max1 = str1.length()-1;
	int x = 0;

	//initialise the result character array	
	char result[] = new char[32];
	for(int z=0;z<32;z++) result[z]= '1';

	for(;x<=max1 && x<32;x++){
		if(str1.charAt(max1-x) == '1') result[31-x] = '0'; else result[31-x] = '1';
	}

	String str3 = new String(result);
	int ret = (java.lang.Long.valueOf(str3,2)).intValue();

	//System.out.println(str1);
	//System.out.println(str3);
	//System.out.println(ret);

	return ret;



}

// shift double a right >> shift places
public static int BitShiftRight(double a, int shift){
	//convert the double to a bitstring
	String str1 = java.lang.Long.toBinaryString((new Double(a)).longValue());

	int max1 = str1.length()-1;
	int x = 0;

	//initialise the result character array	
	char result[] = new char[32];
	for(int z=0;z<32;z++) result[z]= '0';

	for(x=shift;x<=max1 && x<=32;x++){
		if(str1.charAt(max1-x) == '1') result[31-x+shift] = '1';
	}

	String str3 = new String(result);
	int ret = (java.lang.Long.valueOf(str3,2)).intValue();

	//System.out.println(str1);
	//System.out.println(str3);
	//System.out.println(ret);

	return ret;
}

//==========================
// shift double a left << shift places
// convert the double to a bitstring
//==========================

public static int BitShiftLeft(double a, int shift){
	//convert the double to a bitstring
	String str1 = java.lang.Long.toBinaryString((new Double(a)).longValue());

	int max1 = str1.length()-1;
	int x = 0;

	//initialise the result character array	
	char result[] = new char[32];
	for(int z=0;z<32;z++) result[z]= '0';

	for(;x<=max1 && (x+shift)<32;x++){
		if(str1.charAt(max1-x) == '1') result[31-x-shift] = '1';
	}

	String str3 = new String(result);
	int ret = (java.lang.Long.valueOf(str3,2)).intValue();

	//System.out.println(str1);
	//System.out.println(str3);
	//System.out.println(ret);

	return ret;
}

//public static void displayResult(int cycles, int bt, int bnt, int mr, int mw, int instrns){
//	ResultDialog dialog = new ResultDialog();
//	dialog.displayResult(cycles,bt,bnt,mr,mw,instrns);
//}

static public float floatFromInt(int v) {
	//System.out.println("float<-int "+Float.intBitsToFloat(v)+" "+v);
	return Float.intBitsToFloat(v);
}

static public int floatToInt(float d) {
	//System.out.println("float->int "+d+" "+Float.floatToIntBits(d));
	return Float.floatToIntBits(d);   
}

static public t_reg_args Decode_Register(String inputReg) {
	t_reg_args newReg = new t_reg_args();
	if (inputReg.charAt(0) == 'R') {
		newReg.type = 'R';
		newReg.number = Integer.parseInt(inputReg.substring(1));
		newReg.index = 0;
	} else if (inputReg.charAt(0)=='F') {
		newReg.type = 'F';
		newReg.number = Integer.parseInt(inputReg.substring(1));
		newReg.index = 0;
	} else if (inputReg.charAt(0)=='S') {
		newReg.type = 'S';
		newReg.number = Integer.parseInt(inputReg.substring(1));
		newReg.index = 0;
	} else {
		int iParO = inputReg.indexOf('('), iParC = inputReg.indexOf(')');
		newReg.index = Integer.parseInt(inputReg.substring(0,iParO));
		if (inputReg.charAt(iParO+1) == 'R')
			newReg.type = 'R';
		else if (inputReg.charAt(iParO+1) == 'F')
			newReg.type = 'F';
		else if (inputReg.charAt(iParO+1) == 'S')
			newReg.type = 'S';
		newReg.number = Integer.parseInt(inputReg.substring(iParO+2, iParC));
	}
	return newReg;	
}

public static int atoi(String szLabel)
{
	try
	{
		return Integer.parseInt(szLabel);
	}
	catch (NumberFormatException e)
	{
		return 0;
	}
}
/*
static public int Decode_DBL(t_mips_instrn_set instr)
{
	switch(instr.function) {
		case t_mips_instrn_set.MOVD:
		case t_mips_instrn_set.JAL:
		case t_mips_instrn_set.JALR:
			return 1;
		default:
			return 0;
	}
}
*/
static public int is_a_function(t_mips_instrn_set Instruction)
{
	if (Instruction.function == t_mips_instrn_set.VOID
			|| Instruction.function == t_mips_instrn_set.LB
//			|| Instruction.function == t_mips_instrn_set.LBU
			|| Instruction.function == t_mips_instrn_set.SB
			|| Instruction.function == t_mips_instrn_set.LH
//			|| Instruction.function == t_mips_instrn_set.LHU
			|| Instruction.function == t_mips_instrn_set.SH
			|| Instruction.function == t_mips_instrn_set.LW
			|| Instruction.function == t_mips_instrn_set.SW
			|| Instruction.function == t_mips_instrn_set.LWC1
			|| Instruction.function == t_mips_instrn_set.SWC1
			|| Instruction.function == t_mips_instrn_set.ADDI
//			|| Instruction.function == t_mips_instrn_set.ADDIU
			|| Instruction.function == t_mips_instrn_set.SLTI
//			|| Instruction.function == t_mips_instrn_set.SLTIU
			|| Instruction.function == t_mips_instrn_set.ANDI
			|| Instruction.function == t_mips_instrn_set.ORI
			|| Instruction.function == t_mips_instrn_set.XORI
			|| Instruction.function == t_mips_instrn_set.LUI
			|| Instruction.function == t_mips_instrn_set.ADD
//			|| Instruction.function == t_mips_instrn_set.ADDU
			|| Instruction.function == t_mips_instrn_set.SUB
//			|| Instruction.function == t_mips_instrn_set.SUBU
			|| Instruction.function == t_mips_instrn_set.SLT
//			|| Instruction.function == t_mips_instrn_set.SLTU
			|| Instruction.function == t_mips_instrn_set.AND
			|| Instruction.function == t_mips_instrn_set.OR
			|| Instruction.function == t_mips_instrn_set.XOR
			|| Instruction.function == t_mips_instrn_set.NOR
			|| Instruction.function == t_mips_instrn_set.SLL
			|| Instruction.function == t_mips_instrn_set.SRL
			|| Instruction.function == t_mips_instrn_set.SRA
			|| Instruction.function == t_mips_instrn_set.SLLV
			|| Instruction.function == t_mips_instrn_set.SRLV
			|| Instruction.function == t_mips_instrn_set.SRAV
			|| Instruction.function == t_mips_instrn_set.MULT
//			|| Instruction.function == t_mips_instrn_set.MULTU
			|| Instruction.function == t_mips_instrn_set.DIV
//			|| Instruction.function == t_mips_instrn_set.DIVU
			|| Instruction.function == t_mips_instrn_set.MFHI
			|| Instruction.function == t_mips_instrn_set.MTHI
			|| Instruction.function == t_mips_instrn_set.MFLO
			|| Instruction.function == t_mips_instrn_set.MTLO
			|| Instruction.function == t_mips_instrn_set.J
			|| Instruction.function == t_mips_instrn_set.JR
			|| Instruction.function == t_mips_instrn_set.BEQ
			|| Instruction.function == t_mips_instrn_set.BNE
			|| Instruction.function == t_mips_instrn_set.BLEZ
			|| Instruction.function == t_mips_instrn_set.BGTZ
			|| Instruction.function == t_mips_instrn_set.BLTZ
			|| Instruction.function == t_mips_instrn_set.BGEZ
			|| Instruction.function == t_mips_instrn_set.BREAK
			|| Instruction.function == t_mips_instrn_set.NOP
			|| Instruction.function == t_mips_instrn_set.ABSS
			|| Instruction.function == t_mips_instrn_set.ADDS
			|| Instruction.function == t_mips_instrn_set.BC1F
			|| Instruction.function == t_mips_instrn_set.BC1T
			|| Instruction.function == t_mips_instrn_set.CFS
			|| Instruction.function == t_mips_instrn_set.CEQS
			|| Instruction.function == t_mips_instrn_set.COLTS
			|| Instruction.function == t_mips_instrn_set.COLES
			|| Instruction.function == t_mips_instrn_set.CFC1
			|| Instruction.function == t_mips_instrn_set.CTC1
			|| Instruction.function == t_mips_instrn_set.CVTSW
			|| Instruction.function == t_mips_instrn_set.CVTWS
			|| Instruction.function == t_mips_instrn_set.DIVS
			|| Instruction.function == t_mips_instrn_set.MFC1
			|| Instruction.function == t_mips_instrn_set.MOVS
			|| Instruction.function == t_mips_instrn_set.MTC1
			|| Instruction.function == t_mips_instrn_set.MULS
			|| Instruction.function == t_mips_instrn_set.NEGS
			|| Instruction.function == t_mips_instrn_set.SUBS
			)
			return 1;
	return 0;
}



