www.pudn.com > potemkin_sourceforPSP.rar > ARMDataProcessing.cpp


#include "stdafx.h" 
 
#include "../../Globals.h" 
#include "ARM.h" 
#include "ARMCompiler.h" 
#include "ARMAnalyst.h" 
#include "../IR/IR.h" 
 
////////////////////////////////////////////////////////////////////////// 
// ARM 
////////////////////////////////////////////////////////////////////////// 
namespace ARMInstructions 
{ 
 
	//decompose a data processing instruction into IR. Quite a bit of logic! 
	void Comp_bitwise1(u32 op, IROpID irop, bool secondIn, int fm, bool wantsC = false) 
	{ 
		IR_StartBranch(op>>28); 
		InstructionInfo info = CurrentAnalysis(); 
		InstructionInfo opInfo = ARMGetInfo(op); 
			 
		int rd = (op>>12) & 0xF; 
		int rn = (op>>16) & 0xF; 
		int rs = (op>>8 ) & 0xF; 
		int rm = (op    ) & 0xF; 
 
		int Sflag = (op>>20) & 1; 
 
		if (rd == ARM_REG_PC && Sflag) 
			info.flagsOut = 0; 
 
		if ((op&(1<<25))) //imm shift 
		{ 
			u32 cnst = op & 0xFF; 
			u32 shift = ((op >> 8) & 0xF) << 1; 
			u32 shifterOperand = _rotr(cnst,shift); 
 
			u32 shifter_carry_out = shifterOperand>>31; 
			 
			if (shift!=0 && (info.flagsOut & FL_C) && !(fm&FL_C) && !wantsC) 
				IR_Add(IR_SETFLAG,FL_C,0,IRImm(shifter_carry_out)); 
 
			if (secondIn) 
				IR_Add(irop, info.flagsOut&fm, rd, IRReg(rn), IRImm(shifterOperand)); 
			else 
				IR_Add(irop, info.flagsOut&fm, rd, IRImm(shifterOperand)); 
		} 
		else 
		{ 
			int shiftType = (op>>5)&3; 
			if ((op&0x10)) //reg shift 
			{ 
				IROpID shiftOp; 
				switch((op>>5) & 0x3)  
				{ 
				case 0: shiftOp = IR_LSL; break; 
				case 1: shiftOp = IR_LSR; break; 
				case 2: shiftOp = IR_ASR; break; 
				case 3: shiftOp = IR_ROR; break; 
				} 
				IR_Add(shiftOp,wantsC?0:(info.flagsOut&FL_C),IRTEMP0,rm,rs); 
				if (secondIn) 
					IR_Add(irop,   info.flagsOut&fm, rd, IRReg(rn), IRTEMP0); 
				else 
					IR_Add(irop,   info.flagsOut&fm, rd, IRTEMP0); 
				Compiler_AddCycles(1); 
			} 
			else //immediate shift 
			{ 
				u32 shiftAmt = (op>>7) & 0x1F; 
				IROpID shiftOp; 
				bool zero = false; 
				bool copyTop = false; 
				switch((op>>5) & 0x3)  
				{ 
				case 0: shiftOp = IR_LSL; break; 
				case 1: shiftOp = IR_LSR; if (shiftAmt==0) {shiftAmt=32;} break; 
				case 2: shiftOp = IR_ASR; if (shiftAmt==0) {shiftAmt=32;} break; 
				case 3: shiftOp = (shiftAmt==0)?IR_RRX:IR_ROR; break; 
				} 
 
	/*          causes problems with glass 
				if (shiftOp == IR_LSL && irop == IR_MOV) 
				{ 
					IR_Add(shiftOp,wantsC?0:(info.flagsOut&FL_C),rd,rm,IRImm(shiftAmt)); 
				} 
				else*/ 
				{ 
					int tempReg; 
					if (shiftOp == IR_LSL && shiftAmt == 0) 
						tempReg = rm; 
					else 
					{ 
						if (shiftAmt == 32) //hack for big shifts that x86 don't support 
						{                   //possibly this is better done in x86 backend 
							IR_Add(shiftOp,0,IRTEMP0,IRReg(rm),IRImm((u32)31)); 
							IR_Add(shiftOp,info.flagsOut&FL_C,IRTEMP0,IRTEMP0,IRImm((u32)1)); 
						} 
						else 
							IR_Add(shiftOp,wantsC?0:(info.flagsOut&FL_C),IRTEMP0,IRReg(rm),IRImm(shiftAmt)); 
						tempReg = IRTEMP0; 
					} 
					if (secondIn) 
						IR_Add(irop, info.flagsOut&fm, rd, IRReg(rn), IRReg(tempReg)); 
					else 
						IR_Add(irop, info.flagsOut&fm, rd, IRReg(tempReg)); 
				} 
			} 
		} 
		 
		if (rd == ARM_REG_PC) 
		{ 
			//if sflag set RTE so we update cpsr 
			IR_Add(IR_LEAVE,0,0,ARM_REG_PC,Sflag ? IRL_RTE : IRL_BRARM); 
			if (Sflag && irop != IR_MOV && irop != IR_SUB) 
			{ 
				_dbg_assert_msg_(CPU, 0, "Instruction other than MOV and SUB used to return from interrupt"); 
			} 
			if (!IR_IsInBranch()) 
				Compiler_ExitCompile(); 
			Compiler_AddCycles(1); //2 for logical, but hey 
		} 
		IR_EndBranch(); 
	} 
 
	void Comp_AND(u32 op) {Comp_bitwise1(op,IR_AND,true,~FL_C);} 
	void Comp_EOR(u32 op) {Comp_bitwise1(op,IR_XOR,true,~FL_C);} 
	void Comp_ORR(u32 op) {Comp_bitwise1(op,IR_OR,true,~FL_C);} 
	void Comp_BIC(u32 op) {Comp_bitwise1(op,IR_BIC,true,~FL_C);} 
	void Comp_SUB(u32 op) {Comp_bitwise1(op,IR_SUB,true,0xF);} 
	void Comp_RSB(u32 op) {Comp_bitwise1(op,IR_RSB,true,0xF);} 
	void Comp_ADD(u32 op) {Comp_bitwise1(op,IR_ADD,true,0xF);} 
	void Comp_ADC(u32 op) {Comp_bitwise1(op,IR_ADC,true,0xF,true);} 
	void Comp_SBC(u32 op) {Comp_bitwise1(op,IR_SBC,true,0xF,true);} 
	void Comp_RSC(u32 op) {Comp_bitwise1(op,IR_RSC,true,0xF);} 
	void Comp_TST(u32 op) {Comp_bitwise1(op,IR_TST,true,~FL_C);} 
	void Comp_TEQ(u32 op) {Comp_bitwise1(op,IR_TEQ,true,~FL_C);} 
	void Comp_CMP(u32 op) {Comp_bitwise1(op,IR_CMP,true,0xF);} 
	void Comp_CMN(u32 op) {Comp_bitwise1(op,IR_CMN,true,0xF);} 
	void Comp_MOV(u32 op) {Comp_bitwise1(op,IR_MOV,false,~FL_C);} 
	void Comp_MVN(u32 op) {Comp_bitwise1(op,IR_NOT,false,~FL_C);} 
 
	void Comp_CLZ(u32 op)  
	{ 
		IR_StartBranch(op>>28); 
		InstructionInfo &info = CurrentAnalysis(); 
		int rd = (op>>12)&0xF; 
		int rm = (op)&0xF; 
		IR_Add(IR_CLZ,info.flagsOut,rd,IRReg(rm)); 
		IR_EndBranch(); 
	} 
 
 
	//Multiply 
	void Comp_MUL(u32 op)   
	{ 
		IR_StartBranch(op>>28); 
		InstructionInfo &info = CurrentAnalysis(); 
		int rd = (op>>16)&0xF; 
		int rs = (op>>8)&0xF; 
		int rm = (op)&0xF; 
		IR_Add(IR_MUL,info.flagsOut,rd,IRReg(rm),IRReg(rs)); 
		IR_EndBranch(); 
		Compiler_AddCycles(info.flagsOut?3:1); 
	}   
 
	void Comp_MLA(u32 op)    
	{ 
		IR_StartBranch(op>>28); 
		InstructionInfo &info = CurrentAnalysis(); 
		int rd = (op>>16)&0xF; 
		int rn = (op>>12)&0xF; 
		int rs = (op>>8)&0xF; 
		int rm = (op)&0xF; 
		IR_Add(IR_MUL,0,IRTEMP0,rm,rs); 
		IR_Add(IR_ADD,info.flagsOut,rd,IRReg(rn),IRReg(IRTEMP0)); 
		IR_EndBranch(); 
		Compiler_AddCycles(info.flagsOut?3:1); 
	} 
 
	void Comp_UMULL(u32 op)  
	{ 
		InstructionInfo &info = CurrentAnalysis(); 
		int rm =    op&0xf; 
		int rs =   (op>>8)&0xf; 
		int rdhi = (op>>16)&0xf; 
		int rdlo = (op>>12)&0xf; 
		IR_Add(IR_UMUL64,info.flagsOut,rdlo,rm,rs,0,rdhi); 
		Compiler_AddCycles(2); 
	} 
	void Comp_UMLAL(u32 op)  
	{ 
		InstructionInfo &info = CurrentAnalysis(); 
		int rm =    op&0xf; 
		int rs =   (op>>8)&0xf; 
		int rdhi = (op>>16)&0xf; 
		int rdlo = (op>>12)&0xf; 
		IR_Add(IR_UMAD64,info.flagsOut,rdlo,rm,rs,0,rdhi); 
		Compiler_AddCycles(2); 
	} 
	void Comp_SMULL(u32 op)  
	{ 
		InstructionInfo &info = CurrentAnalysis(); 
		int rm =    op&0xf; 
		int rs =   (op>>8)&0xf; 
		int rdhi = (op>>16)&0xf; 
		int rdlo = (op>>12)&0xf; 
		IR_Add(IR_MUL64,info.flagsOut,rdlo,rm,rs,0,rdhi); 
		Compiler_AddCycles(2); 
	} 
	void Comp_SMLAL(u32 op)  
	{ 
		InstructionInfo &info = CurrentAnalysis(); 
		int rm =    op&0xf; 
		int rs =   (op>>8)&0xf; 
		int rdhi = (op>>16)&0xf; 
		int rdlo = (op>>12)&0xf; 
		IR_Add(IR_MAD64,info.flagsOut,rdlo,rm,rs,0,rdhi); 
		Compiler_AddCycles(2); 
	} 
}