⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 instruction.cpp

📁 浙江大学的悟空嵌入式系统模拟器
💻 CPP
字号:
/*
*  Copyright (c) 2005 Zhejiang University, P.R.China
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ 

//=============================================================================
/**
*  \file    ARM/Instruction.cpp
*
*  $Id: Instruction.cpp,v 1.5 2005/06/16 11:26:26 qilj Exp $
*
*  \author  
*/
//=============================================================================

#include "stdafx.h"
#include "./Instruction.h"


namespace ARM {

//	DEFINE_SINGLETON(Instruction)

	int Instruction::version_num = 5;

	Core::Register * Instruction::get_cpsr()
	{
		WUKONG_ASSERT( cpsr_ != NULL );
		return cpsr_;
	}

	void  Instruction::assign(Core::Register &reg, Core::u32 n, Core::u32 m, Core::u32 val)
	{
		std::bitset<8> bit(val);
		for(Core::u32 i = n; i<=m; ++i)
		{		
			reg.set(i, bit.at(i-n));
		}
	}

	void  Instruction::assign_register(Core::Register &reg, Core::u32 n, Core::u32 m, Core::u32 val)
	{
		std::bitset<8> bit(val);
		for(Core::u32 i = n; i<=m; ++i)
		{		
			reg.set(i, bit.at(i-n));
		}
	}


	u32 Instruction::immediate_generator(Core::Binary_32Bit & bits)
	{
		u32 rotate_imm = bits.convert_to_int(8,11);
		u32 immed_8    = bits.convert_to_int(0,7);
		u32 rotate_count = rotate_imm<<1;
		u32 shifter_operand = (immed_8 >> rotate_count) | (immed_8 << (32 - rotate_count));
		u32 bit31 = shifter_operand>>31;
		if(rotate_imm == 0)
			get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29)); // c flag is not change
		else
			get_cpu()->set_shifter_carry_out((u8)bit31);
		return shifter_operand;
	}

	u32 Instruction::shift_imm_generator(Core::Binary_32Bit & bits)
	{
		u32 b6_4 = bits.convert_to_int(4,6);
		u32 b7_4 = bits.convert_to_int(4,7);
		u8 c_flag = get_cpu()->get_cpsr().test(29);
		u32 extra = 0;
		if(bits.convert_to_int(0,3) == 15)
			extra = 4;
		u32 shifter_operand;
		if( b6_4 == 0 )
		{
			u32 shift_imm = bits.convert_to_int(7,11);
			u32 rm_index = bits.convert_to_int(0,3);
			if(shift_imm ==0)
			{
				get_cpu()->read_register(rm_index,shifter_operand);
				shifter_operand += extra;
				get_cpu()->set_shifter_carry_out((u8)c_flag);
			}
			else
			{
				u32 rm_data;
				get_cpu()->read_register(rm_index,rm_data);
				rm_data += extra;
				logical_left(rm_data, shift_imm);
				shifter_operand = rm_data;
			}
		}
		else if( b7_4  == 1 )
		{
			u32 rs_index = bits.convert_to_int(8,11);
			u32 rs_data;
			get_cpu()->read_register(rs_index,rs_data);
			u32 rs7_0 = rs_data % 0x00000100;
			u32 rm_data;
			u32 rm_index = bits.convert_to_int(0,3);
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			if(rs7_0 == 0)
			{
				shifter_operand = rm_data;
				get_cpu()->set_shifter_carry_out(c_flag);
			}
			else if(rs7_0 < 32)
			{
				this->logical_left(rm_data,rs7_0);
				shifter_operand = rm_data;
			}
			else if(rs7_0 == 32)
			{
				shifter_operand = 0;
				get_cpu()->set_shifter_carry_out((u8)rm_data % 2);
			}
			else
			{
				shifter_operand = 0;
				get_cpu()->set_shifter_carry_out(0);
			}
		}
		else if( b6_4  == 2 )
		{
			u32 shift_imm = bits.convert_to_int(7,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			if(shift_imm == 0)
			{
				shifter_operand = 0;
				get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
			}
			else
			{
				logical_right(rm_data,shift_imm);
				shifter_operand = rm_data;
			}
		}
		else if( b7_4 == 3 )
		{
			u32 rs_index = bits.convert_to_int(8,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data,rs_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			get_cpu()->read_register(rs_index,rs_data);
			u32 c_flag = get_cpu()->get_cpsr().test(29);
			u32 rs7_0 = rs_data % 0x00000100;
			if( rs7_0 == 0 )
			{
				shifter_operand = rm_data;
				get_cpu()->set_shifter_carry_out((u8)c_flag);
			}
			else if( rs7_0<32 )
			{
				logical_right(rm_data,rs7_0);
				shifter_operand = rm_data;
			}
			else if( rs7_0 == 32 )
			{
				shifter_operand = 0;
				get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
			}
			else
			{
				shifter_operand = 0;
				get_cpu()->set_shifter_carry_out(0);
			}

		}
		else if( b6_4  == 4 )
		{
			u32 shift_imm = bits.convert_to_int(7,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			if( shift_imm == 0 )
			{
				if( !(rm_data / 0x80000000))
				{
					shifter_operand = 0;
					get_cpu()->set_shifter_carry_out(0);
				}
				else
				{
					shifter_operand = 0xffffffff;
					get_cpu()->set_shifter_carry_out(1);
				}
			}
			else if( shift_imm > 0 )
			{
				u32 rm_index = bits.convert_to_int(0,3);
				u32 rm_data;
				get_cpu()->read_register(rm_index,rm_data);
				rm_data += extra;
				arithmetic_right(rm_data, shift_imm);
				shifter_operand = rm_data;
			}
		}
		else if( b7_4  == 5 )
		{
			u32 rs_index = bits.convert_to_int(8,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data,rs_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			get_cpu()->read_register(rs_index,rs_data);
			u32 rs7_0 = rs_data % 0x00000100;
			if(rs7_0 == 0)
			{
				shifter_operand = rm_data;
				get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29));
			}
			else if(rs7_0 < 32)
			{
				arithmetic_right(rm_data, rs7_0);
				shifter_operand = rm_data;
			}
			else
			{
				if( !(rm_data / 0x80000000))
				{
					shifter_operand = 0;
					get_cpu()->set_shifter_carry_out(0);
				}
				else
				{
					shifter_operand = 0xffffffff;
					get_cpu()->set_shifter_carry_out(1);
				}
			}
		}
		else if( b6_4  == 6 )
		{
			u32 shift_imm = bits.convert_to_int(7,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			if( shift_imm == 0 )
			{
				shifter_operand = rm_data;
				this->rotate_right_extend(shifter_operand,0);
			}
			else
			{	
				rotate_right(rm_data,shift_imm);
				shifter_operand = rm_data;
			}
		}
		else if( b7_4  == 7 )
		{
			u32 rs_index = bits.convert_to_int(8,11);
			u32 rm_index = bits.convert_to_int(0,3);
			u32 rm_data,rs_data;
			get_cpu()->read_register(rm_index,rm_data);
			rm_data += extra;
			get_cpu()->read_register(rs_index,rs_data);
			u32 rs7_0 = rs_data % 0x000000100;
			u32 rs4_0 = rs_data % 0x000000020;
			if( rs7_0 == 0 )
			{
				shifter_operand = rm_data;
				get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29));
			}
			else if( rs4_0 == 0 )
			{
				shifter_operand = rm_data;
				get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
			}
			else 
			{
				this->rotate_right(rm_data,rs4_0);
				shifter_operand = rm_data;
			}
		}
		return shifter_operand;
	}

	void Instruction::rotate_right(u32 & index, int shift_imm)
	{
		Core::Binary_32Bit temp(index);
		get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1))); 
		index = ((index) >> (shift_imm)) | ((index) << (32 - (shift_imm)));
	}

	void Instruction::logical_left(u32 & index, u32 shift_imm)
	{
		Core::Binary_32Bit temp(index);
		get_cpu()->set_shifter_carry_out((u8)(temp.get(32-shift_imm)));
		index = index << shift_imm;
	}

	void Instruction::logical_right(u32 & index, u32 shift_imm)
	{
		Core::Binary_32Bit temp(index);
		get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1)));
		index = index >> shift_imm;
	}

	void Instruction::arithmetic_right(u32 & index ,u32 shift_imm)
	{
		Core::Binary_32Bit temp(index);
		Core::Binary_32Bit temp_operand(0);
		get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1)));
		if(!temp.get(31))
			index = index >> shift_imm;
		else
		{
		for(u32 i = 0;i < shift_imm;i++)
			temp_operand.set((31-i),1);
		index = (index >>shift_imm) | u32(temp_operand.convert_to_int());
		}
	}

	void Instruction::rotate_right_extend(u32 & index, u32 shift_imm)
	{
		get_cpu()->set_shifter_carry_out((u8)index & 0x00000001);
		u32 flag_c =  (get_cpu()->get_cpsr().test(29))<<31;
		index = (index >> 1) | flag_c;
	}

	ARM_CPU * Instruction::get_cpu(void)
	{
		return (ARM_CPU *)(Core::Wukong_Get_System().get_cpu());
	}
} //namespace

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -