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

📄 xscale_mmu.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/XScale_MMU.h
 *
 *  $Id: XScale_MMU.cpp,v 1.2 2005/06/15 12:50:42 jiajc Exp $
 *
 *  \author  Juncheng Jia <jiajuncheng@gmail.com>
 */
//=============================================================================

#include "XScale_MMU.h"

namespace ARM {

XScale_MMU::XScale_MMU()
{
	instr_tlb_ = new TLB(*this, 32);
	data_tlb_ = new TLB(*this, 32);
}

XScale_MMU::~XScale_MMU(void)
{
	delete instr_tlb_;
	delete data_tlb_;
}

u32 XScale_MMU::get_mva(u32 va)
{
	return va;

	if ( va & PID_MAP_MASK)
	{
		return va;
	}
	else 
	{
		u32 value;
		get_cp15()->read_register(CP15::PROCESS_ID, value);
		return va | (value & PID_MAP_MASK);
	}
}

Memory_Result XScale_MMU::instr_read(u32 start, size_t size, Bytecode_Type & buffer)
{
	start = get_mva(start);

	if( is_enable())
	{
		if( ( start & ( WORD_SIZE - 1)) && align_fault_check_on())
		{
			WUKONG_STDOUT <<"ALIGNMENT_FAULT" << std::endl;
			set_fault_status(ALIGNMENT_FAULT);
			set_fault_address(start);
			return ACCESS_FAULT;
		}
		else
		{
			start &= ~(WORD_SIZE -1);
		}

		TLB::Entry * tlb = NULL;

		if( instr_tlb_->ttw(start, &tlb) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		if( instr_tlb_->check_access(start, tlb, true) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		start = instr_tlb_->get_pa(tlb, start);
	}
	
	return mem_access(Memory_32Bit::MEMORY_READ, start, size,buffer);
}

Memory_Result XScale_MMU::data_read(u32 start, size_t size, Bytecode_Type & buffer)
{
	start = get_mva(start);

	if( is_enable())
	{
		if ((start & 3) && (size == 4) && align_fault_check_on() || \
			(start & 1) && (size == 2) && align_fault_check_on() ) 
		{
			WUKONG_STDOUT <<"ALIGNMENT_FAULT" << std::endl;
			set_fault_status(ALIGNMENT_FAULT);
			set_fault_address(start);
			return ACCESS_FAULT;
		}

		TLB::Entry * tlb = NULL;

		if( data_tlb_->ttw(start, &tlb) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		if( data_tlb_->check_access(start, tlb, true) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		start = data_tlb_->get_pa(tlb, start);
	}
	
	mem_access(Memory_32Bit::MEMORY_READ, start, size,buffer);
	return ACCESS_SUCCESSFUL;

}

Memory_Result XScale_MMU::data_write(u32 start, size_t size, Bytecode_Type & buffer)
{
	start = get_mva(start);

	if( is_enable())
	{
		if ((start & 3) && (size == 4) && align_fault_check_on() || \
			(start & 1) && (size == 2) && align_fault_check_on() ) 
		{
			WUKONG_STDOUT <<"ALIGNMENT_FAULT" << std::endl;
			set_fault_status(ALIGNMENT_FAULT);
			set_fault_address(start);
			return ACCESS_FAULT;
		}

		TLB::Entry * tlb = NULL;

		if( data_tlb_->ttw(start, &tlb) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		if( data_tlb_->check_access(start, tlb, false) == ACCESS_FAULT)
		{
			return ACCESS_FAULT;
		}

		start = data_tlb_->get_pa(tlb, start);
	}
	
	mem_access(Memory_32Bit::MEMORY_WRITE, start, size,buffer);
	return ACCESS_SUCCESSFUL;

}

XScale_CP15::XScale_CP15(u32 id) : CP15( id )
{
	
}

XScale_CP15::~XScale_CP15()
{

}

Core::CPU_32Bit * XScale_CP15::get_cpu()
{
	return (Core::CPU_32Bit *)Core::Wukong_Get_System().get_cpu();
}

XScale_MMU * XScale_CP15::get_mmu()
{
	return (XScale_MMU *)(& get_cpu()->get_mmu());
}

void XScale_CP15::on_create()
{
	Core::Processor::Config config;
	config.name = "CP15";
	config.family = "CP_FAMILY";
	for(Core::u32 i = 0; i < 17; ++i)
	{
		Core::Register_File::append_profile(config.register_config, \
			CP15::reg_name_[i], Core::Register_File::REGISTER_32BIT);
	}
	configurate(config);


	// disable MMU
	write_register(CONTROL,0x00000070);
	write_register(ID_CODE,id_code_);
}

void XScale_CP15::on_reset()
{
	write_register(CONTROL,0x00000070);
}

void XScale_CP15::MCR(Core::Instruction_Unit binary)
{
	Binary_32Bit bits(binary);
	u32 opcode1 = bits.convert_to_int(21, 23);
	u32 CRn = bits.convert_to_int(16,19);
	u32 Rd = bits.convert_to_int(12, 15);
	u32 opcode2 = bits.convert_to_int(5, 7);
	u32 CRm = bits.convert_to_int(0, 3);

	if( opcode1 != 0 || Rd == 15 )
	{
		return;
	}

	u32 value;
	get_cpu()->read_register(Rd, value);

	switch( CRn )
	{
	case 0:
		if( opcode2 == 0 )
			write_register(ID_CODE, value);
		else if( opcode2 == 1)
			write_register(CACHE_TYPE, value);
		break;
	case 1:
		write_register(CONTROL, value);
		break;
	case 2:
		write_register(TRANSLATION_TABLE_BASE, value);
		break;
	case 3:
		write_register(DOMAIN, value);
		break;
	case 5:
		write_register(FAULT_STATUS, value);
		break;
	case 6:
		write_register(FAULT_ADDRESS, value);
		break;
	case 7:
		//if( opcode2 == 0 )
		//	get_mmu()->cache_->invalidate_all();
		break;
	case 8:

		if ( opcode2 == 0 )
		{
			get_mmu()->instr_tlb_->invalidate_all();
			get_mmu()->data_tlb_->invalidate_all();
		}
		else if ( opcode2 == 1)
		{
			get_mmu()->instr_tlb_->invalidate(value);
			get_mmu()->data_tlb_->invalidate(value);
		}
		break;



		if ( opcode2 == BINARY4(0000) && CRm == BINARY4(0111) )
		{
			get_mmu()->instr_tlb_->invalidate_all();
			get_mmu()->data_tlb_->invalidate_all();
		}
		else if ( opcode2 == BINARY4(0000) && CRm == BINARY4(0101) )
		{
			get_mmu()->instr_tlb_->invalidate_all();
		}
		else if ( opcode2 == BINARY4(0001) && CRm == BINARY4(0101))
		{
			get_mmu()->instr_tlb_->invalidate(value);
		}
		else if ( opcode2 == BINARY4(0000) && CRm == BINARY4(0110))
		{
			get_mmu()->data_tlb_->invalidate_all();
		}
		else if ( opcode2 ==BINARY4(0001) && CRm == BINARY4(0110))
		{
			get_mmu()->data_tlb_->invalidate(value);
		}
		break;
	case 13:
		value &= MMU::PID_MAP_MASK;
		write_register(PROCESS_ID, value);
		break;
	case 15:
		value &= 0x3fff;
		write_register(COPROCESSOR_ACCESS, value);
		break;
	default:
		assert(0);
	}

}

void XScale_CP15::MRC(Core::Instruction_Unit binary)
{
	Binary_32Bit bits(binary);
	u32 opcode1 = bits.convert_to_int(21, 23);
	u32 CRn = bits.convert_to_int(16,19);
	u32 Rd = bits.convert_to_int(12, 15);
	u32 opcode2 = bits.convert_to_int(5, 7);
	u32 CRm = bits.convert_to_int(0, 3);
	
	if( opcode1 != 0 || Rd == 15 || CRm != 0) 
	{
		return ;
	}

	u32 value;

	switch( CRn )
	{
	case 0:
		if( opcode2 == 0 )
			read_register(ID_CODE, value);
		else if( opcode2 == 1)
			read_register(CACHE_TYPE, value);

		break;
	case 1:
		read_register(CONTROL, value);
		break;
	case 2:
		read_register(TRANSLATION_TABLE_BASE, value);
		break;
	case 3:
		read_register(DOMAIN, value);
		break;
	case 5:
		read_register(FAULT_STATUS, value);
		break;
	case 6:
		read_register(FAULT_ADDRESS, value);
		break;
	case 13:
		read_register(PROCESS_ID, value);
		break;
	case 15:
		read_register(COPROCESSOR_ACCESS, value);
		break;
	default:
		assert(0);
	}

	get_cpu()->write_register(Rd, value);	

}

}

⌨️ 快捷键说明

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