📄 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/Instruction.cpp
*
* $Id: Instruction.cpp,v 1.5 2005/06/16 11:26:26 qilj Exp $
*
* \author
*/
//=============================================================================
#include "stdafx.h"
#include "./Instruction.h"
namespace ARM {
// DEFINE_SINGLETON(Instruction)
int Instruction::version_num = 5;
Core::Register * Instruction::get_cpsr()
{
WUKONG_ASSERT( cpsr_ != NULL );
return cpsr_;
}
void Instruction::assign(Core::Register ®, Core::u32 n, Core::u32 m, Core::u32 val)
{
std::bitset<8> bit(val);
for(Core::u32 i = n; i<=m; ++i)
{
reg.set(i, bit.at(i-n));
}
}
void Instruction::assign_register(Core::Register ®, Core::u32 n, Core::u32 m, Core::u32 val)
{
std::bitset<8> bit(val);
for(Core::u32 i = n; i<=m; ++i)
{
reg.set(i, bit.at(i-n));
}
}
u32 Instruction::immediate_generator(Core::Binary_32Bit & bits)
{
u32 rotate_imm = bits.convert_to_int(8,11);
u32 immed_8 = bits.convert_to_int(0,7);
u32 rotate_count = rotate_imm<<1;
u32 shifter_operand = (immed_8 >> rotate_count) | (immed_8 << (32 - rotate_count));
u32 bit31 = shifter_operand>>31;
if(rotate_imm == 0)
get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29)); // c flag is not change
else
get_cpu()->set_shifter_carry_out((u8)bit31);
return shifter_operand;
}
u32 Instruction::shift_imm_generator(Core::Binary_32Bit & bits)
{
u32 b6_4 = bits.convert_to_int(4,6);
u32 b7_4 = bits.convert_to_int(4,7);
u8 c_flag = get_cpu()->get_cpsr().test(29);
u32 extra = 0;
if(bits.convert_to_int(0,3) == 15)
extra = 4;
u32 shifter_operand;
if( b6_4 == 0 )
{
u32 shift_imm = bits.convert_to_int(7,11);
u32 rm_index = bits.convert_to_int(0,3);
if(shift_imm ==0)
{
get_cpu()->read_register(rm_index,shifter_operand);
shifter_operand += extra;
get_cpu()->set_shifter_carry_out((u8)c_flag);
}
else
{
u32 rm_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
logical_left(rm_data, shift_imm);
shifter_operand = rm_data;
}
}
else if( b7_4 == 1 )
{
u32 rs_index = bits.convert_to_int(8,11);
u32 rs_data;
get_cpu()->read_register(rs_index,rs_data);
u32 rs7_0 = rs_data % 0x00000100;
u32 rm_data;
u32 rm_index = bits.convert_to_int(0,3);
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
if(rs7_0 == 0)
{
shifter_operand = rm_data;
get_cpu()->set_shifter_carry_out(c_flag);
}
else if(rs7_0 < 32)
{
this->logical_left(rm_data,rs7_0);
shifter_operand = rm_data;
}
else if(rs7_0 == 32)
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out((u8)rm_data % 2);
}
else
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out(0);
}
}
else if( b6_4 == 2 )
{
u32 shift_imm = bits.convert_to_int(7,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
if(shift_imm == 0)
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
}
else
{
logical_right(rm_data,shift_imm);
shifter_operand = rm_data;
}
}
else if( b7_4 == 3 )
{
u32 rs_index = bits.convert_to_int(8,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data,rs_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
get_cpu()->read_register(rs_index,rs_data);
u32 c_flag = get_cpu()->get_cpsr().test(29);
u32 rs7_0 = rs_data % 0x00000100;
if( rs7_0 == 0 )
{
shifter_operand = rm_data;
get_cpu()->set_shifter_carry_out((u8)c_flag);
}
else if( rs7_0<32 )
{
logical_right(rm_data,rs7_0);
shifter_operand = rm_data;
}
else if( rs7_0 == 32 )
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
}
else
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out(0);
}
}
else if( b6_4 == 4 )
{
u32 shift_imm = bits.convert_to_int(7,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
if( shift_imm == 0 )
{
if( !(rm_data / 0x80000000))
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out(0);
}
else
{
shifter_operand = 0xffffffff;
get_cpu()->set_shifter_carry_out(1);
}
}
else if( shift_imm > 0 )
{
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
arithmetic_right(rm_data, shift_imm);
shifter_operand = rm_data;
}
}
else if( b7_4 == 5 )
{
u32 rs_index = bits.convert_to_int(8,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data,rs_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
get_cpu()->read_register(rs_index,rs_data);
u32 rs7_0 = rs_data % 0x00000100;
if(rs7_0 == 0)
{
shifter_operand = rm_data;
get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29));
}
else if(rs7_0 < 32)
{
arithmetic_right(rm_data, rs7_0);
shifter_operand = rm_data;
}
else
{
if( !(rm_data / 0x80000000))
{
shifter_operand = 0;
get_cpu()->set_shifter_carry_out(0);
}
else
{
shifter_operand = 0xffffffff;
get_cpu()->set_shifter_carry_out(1);
}
}
}
else if( b6_4 == 6 )
{
u32 shift_imm = bits.convert_to_int(7,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
if( shift_imm == 0 )
{
shifter_operand = rm_data;
this->rotate_right_extend(shifter_operand,0);
}
else
{
rotate_right(rm_data,shift_imm);
shifter_operand = rm_data;
}
}
else if( b7_4 == 7 )
{
u32 rs_index = bits.convert_to_int(8,11);
u32 rm_index = bits.convert_to_int(0,3);
u32 rm_data,rs_data;
get_cpu()->read_register(rm_index,rm_data);
rm_data += extra;
get_cpu()->read_register(rs_index,rs_data);
u32 rs7_0 = rs_data % 0x000000100;
u32 rs4_0 = rs_data % 0x000000020;
if( rs7_0 == 0 )
{
shifter_operand = rm_data;
get_cpu()->set_shifter_carry_out((u8)get_cpu()->get_cpsr().test(29));
}
else if( rs4_0 == 0 )
{
shifter_operand = rm_data;
get_cpu()->set_shifter_carry_out((u8)rm_data / 0x80000000);
}
else
{
this->rotate_right(rm_data,rs4_0);
shifter_operand = rm_data;
}
}
return shifter_operand;
}
void Instruction::rotate_right(u32 & index, int shift_imm)
{
Core::Binary_32Bit temp(index);
get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1)));
index = ((index) >> (shift_imm)) | ((index) << (32 - (shift_imm)));
}
void Instruction::logical_left(u32 & index, u32 shift_imm)
{
Core::Binary_32Bit temp(index);
get_cpu()->set_shifter_carry_out((u8)(temp.get(32-shift_imm)));
index = index << shift_imm;
}
void Instruction::logical_right(u32 & index, u32 shift_imm)
{
Core::Binary_32Bit temp(index);
get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1)));
index = index >> shift_imm;
}
void Instruction::arithmetic_right(u32 & index ,u32 shift_imm)
{
Core::Binary_32Bit temp(index);
Core::Binary_32Bit temp_operand(0);
get_cpu()->set_shifter_carry_out((u8)(temp.get(shift_imm-1)));
if(!temp.get(31))
index = index >> shift_imm;
else
{
for(u32 i = 0;i < shift_imm;i++)
temp_operand.set((31-i),1);
index = (index >>shift_imm) | u32(temp_operand.convert_to_int());
}
}
void Instruction::rotate_right_extend(u32 & index, u32 shift_imm)
{
get_cpu()->set_shifter_carry_out((u8)index & 0x00000001);
u32 flag_c = (get_cpu()->get_cpsr().test(29))<<31;
index = (index >> 1) | flag_c;
}
ARM_CPU * Instruction::get_cpu(void)
{
return (ARM_CPU *)(Core::Wukong_Get_System().get_cpu());
}
} //namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -