Exemple #1
0
void RebuildCppProlog(SYMBOL *sym, int isproto)
{
	int reg_used;
	int reg_alloc;

	int param_count;
	int need_comma;
	int n;

	// Find registers used in function

	reg_used = FunctionRegAnalyse(sym, &funcprop);

	reg_alloc = 0;

	// Output helpful header

	if (isproto == 0)
	{
		RebuildEmit("\n//****************************************\n");
		RebuildEmit("// Function: %s\n", sym->Name);
		RebuildEmit("//****************************************\n\n");
	}

	if (!isproto)
	{
		RebuildEmit("//             rrrrrrrrrrrrrrrriiiiddddddddfrsz\n");
		RebuildEmit("//             fedcba9876543210321076543210rtpr\n");

		RebuildEmit("//src_reg    = %s\n", Bin32(funcprop.src_reg));
		RebuildEmit("//dst_reg    = %s\n", Bin32(funcprop.dst_reg));
		RebuildEmit("//assign_reg = %s\n", Bin32(funcprop.assign_reg));
		RebuildEmit("//uninit_reg = %s\n", Bin32(funcprop.uninit_reg));
		RebuildEmit("//used_reg   = %s\n", Bin32(funcprop.reg_used));
		RebuildEmit("//tfr        = %s\n", Bin32(ThisFunctionRegs));
		RebuildEmit("\n");
	}
	else RebuildEmit("static ");

	// Output function decl
	switch(ThisFunctionRetType)
	{
		case RET_null:
		RebuildEmit(" ?; // Error report to MobileSorcery\n");
		break;

		case RET_void:
		RebuildEmit("void ");
		break;

		case RET_float:
		case RET_int:
		case RET_double:
		RebuildEmit("int ");
		break;
	}

	RebuildEmit("%s_%d(", sym->Name, sym->LocalScope);

	param_count = sym->Params;

	if (param_count > 4)
		param_count = 4;

	need_comma = 0;

	for (n=0;n<param_count;n++)
	{
		if (need_comma)
			RebuildEmit(", ");

		RebuildEmit("int %s", Cpp_reg[REG_i0 + n]);
		need_comma = 1;

		reg_alloc |=  1 << (REG_i0 + n);

	}

	if (isproto)
	{
		RebuildEmit(");\n");
		return;
	}

	RebuildEmit(")\n{\n");

	// Write local decl

	// Remove regs that are already declared in func decl

	// ok this has sort of been reverse engineered by looking at the bitmasks in the rebuilt code... ;)
	// this is added to remove warnings about unusued variables.
	reg_used &= ThisFunctionRegs | (1 << REG_r14) | (1 << REG_r15) | (1 << REG_i0) | (1 << REG_i1) | (1 << REG_i2) | (1 << REG_i3);

	reg_used &= (~reg_alloc);

	// remove sp from locals

	reg_used &= ~(1 << REG_sp);
	reg_used &= ~(1 << REG_zero);

	if (ThisFunctionRetType != RET_null && ThisFunctionRetType != RET_void)
		reg_used |= (1 << REG_r14);
	if (ThisFunctionRetType == RET_double)
		reg_used |= (1 << REG_r15);

	if (reg_used)
	{
		RebuildEmit("\tint ");

		need_comma = 0;

		for (n=0;n<32;n++)
		{
			if (reg_used & (1 << n))
			{
				if (need_comma)
					RebuildEmit(", ");

				RebuildEmit("%s", Cpp_reg[n]);

				if (funcprop.uninit_reg & (1<<n))
					RebuildEmit("=0");

				need_comma = 1;
			}
		}

		RebuildEmit(";\n\n");
	}

}
Exemple #2
0
int FunctionRegAnalyse(SYMBOL *sym, FuncProp *fp)
{
	OpcodeInfo thisOp;
	uchar *ip, *ip_end;
	int params,n;

	fp->src_reg = 0;
	fp->dst_reg = 0;
	fp->assign_reg = 0;
	fp->uninit_reg = 0;
	
	// Make sure we have a valid symbol
	
	if (!sym)
		return -1;

	// Make sure the symbol is a function

	if (sym->Type != SECT_code)
		return -1;

	// Get the start and end of the function in the code array

	ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP);
	ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value);

	// Set up the parameter regs
	
	params = sym->Params;
	
	for (n=0;n<params;n++)
	{
		fp->assign_reg |=  REGBIT(REG_i0 + n);
	}
	
	// Scan the function

#ifdef AFDEBUG
	printf("\n");
#endif

	while(1)
	{		
		if (ip > ip_end)
			break;

#ifdef AFDEBUG
		{
			char buf[2560];
			buf[0] = 0;
			DisassembleFromSource(ip - CodeMemArray.array, buf);
			printf("%s\n", buf);
		}
#endif
	
		ip = DecodeOpcode(&thisOp, ip);

		// Ignor push and pop
		
		if (thisOp.op == _PUSH)
			continue;

		if (thisOp.op == _POP)
			continue;

		//-----------------------------------------
		// Deal with syscalls
		// for some strange reason rd is the syscallId which will
		// tag unused registers as used for void functions
		//-----------------------------------------

		if(thisOp.op == _SYSCALL)
		{
			FunctionReg_Syscall(&thisOp, fp);
		}

		// Check for a dest reg		
		else if (thisOp.flags & fetch_d)
		{
			if (thisOp.rd < 32)
			{
				// Since this is a dst regs we say its initialized
				fp->assign_reg |=  REGBIT(thisOp.rd);
	
				// Say this reg was used as a dst reg
				fp->dst_reg |= REGBIT(thisOp.rd);
			}
		}

		// Check for a source reg
		
		if (thisOp.flags & fetch_s)
		{
			if (thisOp.rs < 32)
			{
				// check if this reg was assigned previously, if it was'nt it is uninitialized before use
			
				int is_assigned = fp->assign_reg & REGBIT(thisOp.rs);
			
				if (!is_assigned)
					fp->uninit_reg |= REGBIT(thisOp.rs);
			
				fp->src_reg |= REGBIT(thisOp.rs);
			}
		}

		//-----------------------------------------
		//		Deal with immediate calls
		//-----------------------------------------
		
		// Add the call parameters to the used list

		if (thisOp.op == _CALLI)
		{

			FunctionReg_Calli(&thisOp, fp);
		}

		//-----------------------------------------
		//		Deal with register calls
		//-----------------------------------------
		
		// Add the call parameters to the used list

		if (thisOp.op == _CALL)
		{
			FunctionReg_CallReg(&thisOp, fp);
		}
	}


#ifdef AFDEBUG

	printf("\n");

	printf("                  rrrrrrrrrrrrrrrriiiiddddddddfrsz\n");
	printf("                  fedcba9876543210321076543210rtpr\n");

	printf("src_reg = %s\n", Bin32(fp->src_reg));
	printf("dst_reg = %s\n", Bin32(fp->dst_reg));
	printf("assign_reg    = %s\n", Bin32(fp->assign_reg));
	printf("uninit_reg      = %s\n", Bin32(fp->uninit_reg));

	if (fp->uninit_reg)
		printf("");

#endif

	// Make sure zr is never uninitialized
	
	fp->uninit_reg &= ~REGBIT(REG_zero);

	// Make a composit of which reg's were used

	fp->reg_used = fp->src_reg | fp->dst_reg;

	return fp->reg_used;
}