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

📄 mls_instruction.cpp

📁 浙江大学的悟空嵌入式系统模拟器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
*  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/MLS_Instruction.h
*
*  $Id: MLS_Instruction.cpp,v 1.4 2005/06/08 07:40:45 qilj Exp $
*
*  \author  Jie Chen <alt_alt@163.com> 
*/
//=============================================================================


#include "./MLS_Instruction.h"

namespace ARM{

	DEFINE_SINGLETON(MLS_Instruction)

		void MLS_Instruction::execute(Core::Instruction_Unit  binary)
	{
		
		Core::Binary_32Bit bits(binary);
		u32 opcode = bits.convert_to_int(20,22) * 2;
		opcode += bits.get(15);
		switch(opcode)
		{
		case 5:
			return STM1(binary);
		case 3:
			return LDM1(binary);
		case 4:
			return STM1(binary);
		case 0:
			return STM1(binary);
		case 2:
			return LDM1(binary);
		case 6:
			return LDM1(binary);
		case 11:
			return LDM3(binary);
		case 8:
			return STM2(binary);
		case 10:
			return LDM2(binary);
		case 7:
			return LDM1(binary);
		case 15:
			return LDM3(binary);
		case 1:
			return STM1(binary);
		case 9:
			return STM2(binary);
			//		default:
			//			return UND;
		}
	}

	void MLS_Instruction::bit_num(u32 & num,Core::Instruction_Unit & binary,u32 start,u32 end)
	{
		u32 i;
		Core::Binary_32Bit bits(binary);
		for(i = start;i<=end;i++)
		{
			if(bits.get(i))
				num++;
		}
	}

	u32 MLS_Instruction::multi_address(Core::Instruction_Unit & binary,u32 & start_address,u32 & end_address)
	{
		Core::Binary_32Bit bits(binary);
		u32 rn_index = bits.convert_to_int(16,19);
		u32 num = 0;
		this->bit_num(num,binary,0,15);
		u32 rn_data;
		get_cpu()->read_register(rn_index,rn_data);
		switch(bits.convert_to_int(23,24))
		{
		case 1://1
			{
				//IA
				start_address = rn_data;
				end_address = start_address + num * 4 - 4;
				if(bits.get(21))
					get_cpu()->write_register(rn_index,rn_data + num * 4);
				start_address = start_address & 0xfffffffc;
				end_address = end_address & 0xfffffffc;
				return rn_data;
			}
		case 3://3
			{
				//IB
				start_address = rn_data + 4;
				end_address = start_address - 4 + num * 4;//end_address = rn + num * 4
				if(bits.get(21))
					get_cpu()->write_register(rn_index,rn_data + num * 4);
				start_address = start_address & 0xfffffffc;
				end_address = end_address & 0xfffffffc;
				return rn_data;
			}
		case 0://0
			{
				//DA
				end_address = rn_data;
				start_address = end_address + 4 - num * 4;
				if(bits.get(21))
					get_cpu()->write_register(rn_index,start_address - 4);
				start_address = start_address & 0xfffffffc;
				end_address = end_address & 0xfffffffc;
				return rn_data;
			}
		case 2://2
			{
				//DB
				end_address = rn_data - 4;
				start_address = end_address + 4 - num * 4;
				if(bits.get(21))
					get_cpu()->write_register(rn_index,end_address + 4 - num * 4);
				start_address = start_address & 0xfffffffc;
				end_address = end_address & 0xfffffffc;
				return rn_data;
			}
		}
	}

	void MLS_Instruction::get_usermode_address(Core::Instruction_Unit & binary,u32 & addr)
	{
		//need func for usemode
		u32 offset_12;
		Core::Binary_32Bit bits(binary);
		u32 rn_index = bits.convert_to_int(16,19);
		u32 extra;
		u32 rn_data;
		get_cpu()->read_user_register(rn_index,rn_data);
		if(rn_index == 15)
			extra = 4;
		else
			extra = 0;
		u32 u_3 = bits.convert_to_int(23,25);
		u32 u_1 = bits.get(21);
		if(u_3 == 1 && u_1 == 1)//3
		{
			//addr = rn
			//if(cond)
			//rn = rn + offset_12
			addr = rn_data;
			{
				offset_12 = bits.convert_to_int(0,11);
				get_cpu()->write_user_register(rn_index,rn_data + offset_12);
			}
			return ;
		}
		if(u_3 == 0 && u_1 == 1)//1
		{
			//addr = rn
			//if(cond)
			//rn = rn -offset_12
			addr = rn_data;
			{
				offset_12 = bits.convert_to_int(0,11);
				get_cpu()->write_user_register(rn_index,rn_data - offset_12);
			}
			return ;
		}
		if(u_3 == 4 && u_1 == 1)//9
		{	
			//addr = rn
			//if(cond)
			//rn = rn - rm or rn = rn - rm shift imm
			addr = rn_data;
			{
				u32 rm_index = bits.convert_to_int(0,3);
				u32 rm_data;
				get_cpu()->read_user_register(rm_index,rm_data);
				if(bits.convert_to_int(4,11) == 0)
					get_cpu()->write_user_register(rn_index,rn_data - rm_data);
				else
				{
					//shift rm here
					//	rm_index = this->BITS(instr,0,3);
					//	Register_32bit & rm = this->get_register(rm_index);
					u32 index = rm_data;
					this->shft_rm(binary,index);
					get_cpu()->write_user_register(rn_index,rn_data - index);
				}
			}
			return ;		
		}
		if(u_3 == 5 && u_1 == 1)//11
		{
			//addr = rn 
			//if(cond)
			//rn = rn + rm or rn = rn + rm shift imm
			addr = rn_data;
			{
				u32 rm_index = bits.convert_to_int(0,3);
				u32 rm_data;
				get_cpu()->read_user_register(rm_index,rm_data);
				if(bits.convert_to_int(4,11) == 0)
					get_cpu()->write_user_register(rn_index,rn_data + rm_data);
				else
				{
					//shift rm here
					u32 index = rm_data;
					this->shft_rm(binary,index);
					get_cpu()->write_user_register(rn_index,rn_data - index);
				}
			}
			return ;
		}
	}
	void MLS_Instruction::LDM1(Core::Instruction_Unit & binary)
	{
		Core::Binary_32Bit bits(binary);
		u32 start_address,end_address,addr,value;
		Core::Bytecode_Type buffer;
		Core::Error_Type error_no;
		u32 original_rn = this->multi_address(binary,start_address,end_address);
		addr = start_address;
		for(u32 i = 0;i<15;i++)
		{
			if(bits.get(i))
			{
				/*if((error_no = (Core::Error_Type)get_cpu()->get_mmu().access(Memory_32Bit::MEMORY_READ,addr,4,buffer)) != 0);
				//					Core::Wukong_Get_System()	.set_last_error(error_no);*/

				if ( (get_cpu()->get_mmu().access(Core::Memory_32Bit::MEMORY_READ, addr, 4, buffer)) == MMU::PAGE_TRANSLATION_FAULT)
				{
					if(ARM::Instruction::version_num == 5)
					{
						u32 rn_index = bits.convert_to_int(16,19);
						get_cpu()->write_register(rn_index,original_rn);
					}
					get_cpu()->on_dataabt_exception(); 
					return;
				}
				Wukong_Get_System().convert_from_bytecode(buffer,value);
				get_cpu()->write_register(i,value);
				addr += 4;
				buffer.clear();
			}
		}
		if(bits.get(15))
		{
			/*if((error_no = get_cpu()->get_mmu().access(Memory_32Bit::MEMORY_READ,addr,4,buffer)) != 0);
			//				Wukong_Get_System().set_last_error(error_no);	*/

			if ( (get_cpu()->get_mmu().access(Core::Memory_32Bit::MEMORY_READ, addr, 4, buffer)) == MMU::PAGE_TRANSLATION_FAULT)
			{
				if(ARM::Instruction::version_num == 5)
				{
					u32 rn_index = bits.convert_to_int(16,19);
					get_cpu()->write_register(rn_index,original_rn);
				}
				get_cpu()->on_dataabt_exception(); 
				return;
			}
			Wukong_Get_System().convert_from_bytecode(buffer,value);
			//architecture 5 or above has different ways to deal with it
			if(ARM::Instruction::version_num == 5)
				get_cpu()->write_register(15,value & 0xfffffffe);
			else
				get_cpu()->write_register(15,value & 0xfffffffc);
			addr += 4;
			buffer.clear();
		}
		assert(end_address == addr - 4);

⌨️ 快捷键说明

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