📄 cpu.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 Processor/PPC/CPU.cpp
*
* \author Chenfeng Zhou <ini_autumn@163.com>
*
* Created: <2005-02-08 14:10:08 by Cheney Chow>
* Last update: <2005-02-09 20:51:10 by Cheney Chow>
*
* $Id: CPU.cpp,v 1.1 2005/06/16 06:01:44 qilj Exp $
*/
//=============================================================================
#include <iostream>
#include <cstdio>
#include <string>
#include "CPU.h"
#include "Utils/Logger.h"
#include "Utils/Debug.h"
#include "Register.h"
#include "Exception.h"
#include "Utils/Logger.h"
#include "Core/Log.h"
#include "Core/Helper.h"
#include "Core/ConfigFile.h"
#include "Reg_Flag.h"
#include "Reg_Utils.h"
#include "MMU.h"
namespace PPC {
PPC_CPU::PPC_CPU (Core::Instruction_Set &instru_set, PPC_MMU *mmu)
: Core::CPU_32Bit (instru_set, mmu)
, reg_file_adaptor_ (reg_file_.get())
{
#ifdef PPC_DEBUG
if (PPC::Logger::instance()->init_logfile(Core::Host_Machine::get_log_path() + "\\log.txt") < 0) {
std::cout<<"open log error";
exit(0);
}
#endif
init_cpu();
}
PPC_CPU::~PPC_CPU () {}
void PPC_CPU::on_create()
{}
void PPC_CPU::run ()
{
if ( OS_LINUX == os_type () )
switch_mmu();
running_ = true;
while (running_) {
npc_ = pc_ + 4;
current_instr_ = fetch_instruction(pc_);
//if (pc_ == 0xc000124c)
// Logger::instance()->enable_trace();
#if defined(UNIT_TEST)
// if it's 'rfi', we exit; just for unit test;
if (current_instr_ == 0x4c000064)
return;
#endif
if ( OS_UCOS == os_type() ) {
if (ucos_ee_handler()) {
pc_ = npc_;
continue;
}
}
get_instr_set().execute_instruction (current_instr_);
post_routine ();
//For debug
//DUMP_CPU_STATE;
pc_ = npc_;
// Todo: some exception jobs
}
}
void PPC_CPU::post_routine ()
{
cpu_state_.ops++;
cpu_state_.ptb++;
if (OS_UCOS == os_type ()) {
if (cpu_state_.pdec == 0) {
cpu_state_.pdec = (Core::u64)0xf0;
if (cpu_state_.enable_ee) {
//if (REG_BIT_IS_SET(MSR, Reg_Flag::MSR_EE)) {
Exception_Mgr::instance()->pend_exception(Exception::EXC_DEC);
}
}
else
cpu_state_.pdec--;
//if (cpu_state_.enable_ee)
Exception_Mgr::instance()->handle_pending_exception ();
}
}
int PPC_CPU::init_cpu ()
{
init_reg_file ();
/// loader set pc...
/// no pc-initialization job need to be done when we use ELF_LOADER;
init_cpu_state ();
return PPC_SUCCESS;
}
int PPC_CPU::init_reg_file ()
{
reg_file_adaptor_.init();
//! Register CPU as 440GP Rev. B
//!
//! Different CPU types don't have same time frequency
//! even when they have same version number but different
//! Reversion number;
reg_file_adaptor_[PVR].convert_from_int(0x40000440);
return 0;
}
void PPC_CPU::init_cpu_state()
{
cpu_state_.ops = 0;
cpu_state_.ptb = 0;
cpu_state_.pdec = 0xf0;
cpu_state_.enable_ee = false;
cpu_state_.cpu_stop = false;
Core::Config_File * cf = Core::Wukong_Get_System().get_config();
PPC_ASSERT(cf);
std::string cf_os;
cf->read("/kernel/name", cf_os);
cpu_state_.os = (cf_os == "UCOS")? OS_UCOS : OS_LINUX;
}
PPC_Instr_T PPC_CPU::fetch_instruction(PPC_Address_T pc)
{
Core::u32 res;
Core::Bytecode_Type buffer;
/**
* For Linux:
* If there's an instruction page fault, mmu raise an exception;
* npc is reset, and we then fetch the instruction at the begin of
* corresponding exception_handler's code.
*
* For Ucos:
* There's no mmu, so there's no page fault considered.
*/
Core::Memory_Access_Type read_type = (OS_UCOS == os_type())?
Core::Memory_32Bit::MEMORY_READ :
MMU::INSTR_READ;
if (MMU::ACCESS_FAULT == get_mmu().access(read_type,
(Core::u32)pc,
4, buffer))
get_mmu().access(MMU::INSTR_READ, (Core::u32)npc_, 4, buffer);
Core::Wukong_Get_System().convert_from_bytecode(buffer, res);
return (PPC_Instr_T)res;
}
} // namespace PPC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -