📄 mls_instruction.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/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 + -