📄 arm_processor.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 Arch/ARM/ARM_Processor.cpp
*
* $Id: ARM_Processor.cpp,v 1.2 2005/06/16 11:27:06 qilj Exp $
*
* \author zhao jun <junzhao_china@yahoo.com.cn>
Lingjie Qi <lingjie_qi@163.com>
*/
//=============================================================================
#include "./ARM_Processor.h"
#include "Core/Memory.h"
#include "Compare.h"
#include "MMU.h"
namespace ARM{
std::string ARM_CPU::reg_name_[(Core::u32)ARM_CPU::REG_END] = {
"R0","R1","R2","R3",
"R4","R5","R6","R7",
"R8","R9","R10","R11",
"R12","R13","R14","R15",
"R8_fiq","R9_fiq","R10_fiq","R11_fiq",
"R12_fiq","R13_fiq","R14_fiq",
"R13_irq","R14_irq",
"R13_svc","R14_svc",
"R13_abt","R14_abt",
"R13_und","R14_unds",
"CPSR",
"SPSR_svc","SPSR_abt",
"SPSR_und","SPSR_irq","SPSR_fiq"
};
ARM_CPU::ARM_CPU(Core::Instruction_Set & instr_set, Core::MMU<Core::u32> * mmu)
: Core::CPU_32Bit(instr_set, mmu)
{
//set pc
}
void ARM_CPU::on_create()
{
configurate(config_);
}
void ARM_CPU::load_register()
{
Core::u32 reg_count = (Core::u32)ARM_CPU::REG_END - 1;
WUKONG_ASSERT(reg_count != 0);
for(Core::u32 i =0; i<reg_count; ++i)
{
Core::Register_File::append_profile(config_.register_config, \
ARM_CPU::reg_name_[i], Core::Register_File::REGISTER_32BIT);
}
}
Core::Instruction_Unit ARM_CPU::fetch_instruction(Core::u32 pc)
{
Core::u32 res;
Core::Bytecode_Type buffer;
if ( (get_mmu().access(Core::Memory_32Bit::MEMORY_READ, pc, 4, buffer)) == MMU::PAGE_TRANSLATION_FAULT)
{
this->on_prefetch_exception();
factual_pc_ = pc;
res = 0xFFFFFFFE ;
return (Core::Instruction_Unit)res;
}
else
Core::Wukong_Get_System().convert_from_bytecode(buffer, res);
factual_pc_ = pc;
set_pc(pc+4);
return (Core::Instruction_Unit)res;
}
void ARM_CPU::adjust_reg_idx(size_t &idx)
{
WUKONG_ASSERT(idx>=0 && idx <=15);
switch(current_mode_)
{
case User:
break;
case Svc:
if(idx >= 13 && idx <=14)
idx += 12;
break;
case IRQ:
if(idx >= 13 && idx <= 14)
idx += 10;
break;
case FIQ:
if(idx >= 8 && idx <= 14)
idx += 8;
break;
case Sys:
break;
case Abt:
if(idx >= 13 && idx <= 14)
idx += 14;
break;
case Und:
if(idx >=13 && idx <= 14)
idx += 16;
break;
default:
break;
}
}
bool ARM_CPU::read_register(size_t idx, Core::Register_Int & val)
{
adjust_reg_idx(idx);
val = reg_file_->get_register(idx).convert_to_int();
return true;
}
bool ARM_CPU::read_user_register(size_t idx, Core::Register_Int & val)
{
val = reg_file_->get_register(idx).convert_to_int();
return true;
}
bool ARM_CPU::write_register(size_t idx, Core::Register_Int val)
{
adjust_reg_idx(idx);
Core::Register & reg = reg_file_->get_register(idx);
reg.convert_from_int(val);
return true;
}
bool ARM_CPU::write_user_register(size_t idx, Core::Register_Int val)
{
Core::Register & reg = reg_file_->get_register(idx);
reg.convert_from_int(val);
return true;
}
void ARM_CPU::do_exception(CPU_Interrupt exp)
{
//set current interrupt's priority
this->current_exp_priority_ = exp;
switch(exp)
{
case ARM_CPU::Rst_exp:
on_reset_exception();
break;
case ARM_CPU::Undef_exp:
on_undefined_instruction();
break;
case ARM_CPU::PreAbt_exp:
on_prefetch_exception();
break;
case ARM_CPU::DataAbt_exp:
on_dataabt_exception();
break;
case ARM_CPU::IRQ_exp:
on_irq_exception();
break;
case ARM_CPU::FIQ_exp:
on_fiq_exception();
break;
case ARM_CPU::SWI_exp:
on_swi_exception();
break;
default:
break;
}
}
void ARM_CPU::run(void)
{
Core::Board_32Bit * board = (Core::Board_32Bit *) Core::Wukong_Get_System().get_board();
assert(board);
running_ = true;
Core::Bytecode_Type buffer,buf;
while(running_)
{
board->poll_extern_exception();
Core::Instruction_Unit binary = fetch_instruction(get_pc());
if ( !(instr_set_.execute_instruction(binary)) )
{
on_undefined_instruction();
}
board->io_do_cycle();
Core::Interrupt_Type intrp = board->get_highest_interrupt();
board->on_interrupt(intrp);
}
}
ARM_Coprocessor * ARM_CPU::get_coprocessor(size_t index)
{
return (ARM_Coprocessor *)coprocessors_[index];
}
void ARM_CPU::debugging_run()
{
Core::Board_32Bit * board = (Core::Board_32Bit *) Core::Wukong_Get_System().get_board();
assert(board);
Core::Debugger * debugger = Core::Wukong_Get_System().get_debugger();
assert(debugger);
set_break(true);
debugger->debug(*this);
running_ = true;
while(running_)
{
if (is_break()) continue;
//todo
board->poll_extern_exception();
Core::Interrupt_Type intrp = board->get_highest_interrupt();
board->on_interrupt(intrp);
Core::Instruction_Unit binary = fetch_instruction(get_pc());
if ( !(instr_set_.execute_instruction(binary)) )
{
on_undefined_instruction(binary);
}
if(con_)
{
con_ = false;
if(current_bpt_.addr != -1)
{
std::map<Core::u32, BreakPoint>::iterator pos;
pos = bpt_map_.find(current_bpt_.addr);
if( pos != bpt_map_.end() )
{
Core::Bytecode_Type buffer;
Core::Wukong_Get_System().convert_to_bytecode(0xFFFFFFFF, buffer);
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, current_bpt_.addr, 4, buffer);
}
current_bpt_.addr = -1;
}
}
if (is_single_step())
{
set_break(true);
set_single_step(false);
if(current_bpt_.addr != -1)
{
std::map<Core::u32, BreakPoint>::iterator pos;
pos = bpt_map_.find(current_bpt_.addr);
//WUKONG_ASSERT( pos = bpt_map_.end() );
if( pos != bpt_map_.end() )
{
Core::Bytecode_Type buffer;
Core::Wukong_Get_System().convert_to_bytecode(0xFFFFFFFF, buffer);
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, current_bpt_.addr, 4, buffer);
}
current_bpt_.addr = -1;
}
}
}
}
Core::s32 ARM_CPU::insert_breakpoint(Core::Debugger::Breakpoint_Type btype,Core::u32 addr, size_t len)
{
Core::Bytecode_Type buffer;
BreakPoint bp;
bp.addr = addr;
Core::u32 val = 0;
get_mmu().access(Core::Memory_32Bit::MEMORY_READ, addr, len, buffer);
Core::Wukong_Get_System().convert_from_bytecode(buffer, val);
bp.res = buffer;
Core::Wukong_Get_System().convert_to_bytecode(0xFFFFFFFF, buffer);
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, addr, len, buffer);
switch(btype)
{
case Core::Debugger::MEMORY_BREAKPOINT:
bp.btype = btype;
break;
case Core::Debugger::HARDWARE_BREAKPOINT:
bp.btype = btype;
break;
case Core::Debugger::WRITE_WATCHPOINT:
bp.btype = btype;
break;
case Core::Debugger::READ_WATCHPOINT:
bp.btype = btype;
break;
case Core::Debugger::ACCESS_WATCHPOINT:
bp.btype = btype;
break;
default:
return -1;
}
if( val != 0xFFFFFFFF)
{
//set many breakpoint in address
bpt_map_.insert(std::pair<Core::u32, BreakPoint>(addr, bp));
}
return addr;
}
Core::s32 ARM_CPU::remove_breakpoint(Core::Debugger::Breakpoint_Type btype,Core::u32 addr, size_t len)
{
std::map<Core::u32, BreakPoint>::iterator pos;
pos = bpt_map_.find(addr);
WUKONG_ASSERT( pos != bpt_map_.end() );
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, addr, len, bpt_map_[addr].res);
bpt_map_.erase(pos);
return addr;
}
void ARM_CPU::step_info()
{
if(current_bpt_.addr != -1)//jump last 1 instruction
{
set_pc(current_bpt_.addr);
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, current_bpt_.addr, 4, current_bpt_.res);
//current_bpt_ = NULL;
}
set_single_step(true);
}
void ARM_CPU::step_over()
{
}
void ARM_CPU::con()
{
if(current_bpt_.addr != -1)
{
set_pc(current_bpt_.addr);
get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, current_bpt_.addr, 4, current_bpt_.res);
}
set_break(false);
set_single_step(false);
con_ = true;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -