00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef EMU_UTILITY_COMMON_EMULATOR_H
00033 #define EMU_UTILITY_COMMON_EMULATOR_H
00034
00035 #include "Emu/Utility/GenericOperation.h"
00036 #include "Interface/EmulatorIF.h"
00037 #include "Interface/OpStateIF.h"
00038 #include "Interface/OpClassCode.h"
00039 #include "Env/Param/ParamExchange.h"
00040 #include "SysDeps/Endian.h"
00041 #include "Emu/Utility/System/Syscall/SyscallConvIF.h"
00042 #include "Emu/Utility/System/ProcessState.h"
00043 #include "Emu/Utility/System/Memory/MemorySystem.h"
00044 #include "Emu/Utility/System/Memory/MemoryUtility.h"
00045 #include "Emu/Utility/System/VirtualSystem.h"
00046 #include "Emu/Utility/ExtraOpInfoWrapper.h"
00047 #include "Emu/Utility/OpEmulationState.h"
00048 #include "Emu/Utility/SkipOp.h"
00049 #include "Emu/Utility/GenericOperation.h"
00050
00051 namespace Onikiri {
00052 class SystemIF;
00053
00054 namespace EmulatorUtility {
00055
00056
00057 template <class Traits>
00058 class CommonEmulator :
00059 public EmulatorIF,
00060 public MemIF,
00061 public ParamExchange
00062 {
00063 private:
00064
00065
00066 typedef typename Traits::ISAInfoType ISAInfoType;
00067 typedef typename Traits::OpInfoType OpInfoType;
00068 typedef typename Traits::ConverterType ConverterType;
00069 typedef typename Traits::LoaderType LoaderType;
00070 typedef typename Traits::SyscallConvType SyscallConvType;
00071
00072 typedef ParamExchange ParamExchangeType;
00073 public:
00074 CommonEmulator( SystemIF* simSystem );
00075 virtual ~CommonEmulator();
00076
00077
00078 using ParamExchangeType::LoadParam;
00079 using ParamExchangeType::ReleaseParam;
00080 using ParamExchangeType::GetRootPath;
00081 using ParamExchangeType::ParamEntry;
00082
00083
00084 virtual std::pair<OpInfo**, int> GetOp(PC pc);
00085 virtual MemIF* GetMemImage();
00086 virtual void Execute(OpStateIF* op, OpInfo* opinfo);
00087 virtual void Commit(OpStateIF* op, OpInfo* opinfo);
00088 virtual int GetProcessCount() const;
00089 virtual PC GetEntryPoint(int pid) const;
00090 virtual u64 GetInitialRegValue(int pid, int index) const;
00091 virtual ISAInfoIF* GetISAInfo();
00092 virtual PC Skip(PC pc, u64 skipCount, u64* regArray, u64* executedInsnCount, u64* executedOpCount);
00093 virtual void SetExtraOpDecoder( ExtraOpDecoderIF* extraOpDecoder );
00094
00095
00096 virtual void Read( MemAccess* access );
00097 virtual void Write( MemAccess* access );
00098
00099 private:
00100 bool CreateProcesses( SystemIF* simSystem );
00101
00102
00103 std::pair<OpInfo**, int> GetOpBody(PC pc);
00104
00105 ISAInfoType m_alpha64Info;
00106 std::vector<EmulatorUtility::ProcessState*> m_processes;
00107 ConverterType m_insnConverter;
00108
00109
00110 boost::pool<> m_opInfoArrayPool;
00111 boost::object_pool< OpInfoType > m_opInfoPool;
00112 boost::object_pool< ExtraOpInfoWrapper<ISAInfoType> > m_exOpInfoWrapperPool;
00113
00114 class CodeWordHash
00115 {
00116 public:
00117 size_t operator()(const u32 value) const
00118 {
00119 return (size_t)((value >> 26) ^ value);
00120 }
00121 };
00122
00123 typedef std::pair<OpInfo**, int> OpInfoArray;
00124 std::vector< std::vector< OpInfoArray > > m_ProcessOpInfoCache;
00125
00126 typedef unordered_map<u32, OpInfoArray, CodeWordHash> CodeWordOpInfoMap;
00127 CodeWordOpInfoMap m_codeWordToOpInfo;
00128
00129
00130 int m_processCount;
00131
00132
00133 ExtraOpDecoderIF* m_extraOpDecoder;
00134
00135
00136 bool m_enableResultCRC;
00137 typedef typename boost::crc_32_type CRC_Type;
00138 std::vector< CRC_Type > m_resultCRCs;
00139 void CalcCRC( const PC& pc, u64 dstResult );
00140 std::vector< u32 > GetCRC_Result()
00141 {
00142 std::vector< u32 > result;
00143 for( std::vector< CRC_Type >::iterator i = m_resultCRCs.begin();
00144 i != m_resultCRCs.end();
00145 ++i
00146 ){
00147 result.push_back( (*i)() );
00148 }
00149 return result;
00150 }
00151
00152 public:
00153
00154 BEGIN_PARAM_MAP( "" )
00155 BEGIN_PARAM_PATH( "/Session/Emulator/" )
00156 PARAM_ENTRY( "@EnableResultCRC32Calculation", m_enableResultCRC )
00157 BEGIN_PARAM_PATH("Processes/")
00158 PARAM_ENTRY("count(Process)", m_processCount)
00159 END_PARAM_PATH()
00160 END_PARAM_PATH()
00161 RESULT_ENTRY( "/Session/Result/System/@ResultCRC32", GetCRC_Result() )
00162 END_PARAM_MAP()
00163 };
00164
00165 template <class Traits>
00166 CommonEmulator<Traits>::CommonEmulator( SystemIF* simSystem )
00167 : m_opInfoArrayPool(sizeof(OpInfo*)),
00168 m_extraOpDecoder(0),
00169 m_enableResultCRC( false )
00170 {
00171
00172 LoadParam();
00173 if (!CreateProcesses(simSystem)) {
00174 THROW_RUNTIME_ERROR("failed to create target processes.");
00175 }
00176 Operation::testroundmode(NULL);
00177 }
00178
00179 template <class Traits>
00180 CommonEmulator<Traits>::~CommonEmulator()
00181 {
00182 for (std::vector<ProcessState*>::iterator e = m_processes.begin(); e != m_processes.end(); ++e) {
00183 delete *e;
00184 }
00185
00186 ReleaseParam();
00187 }
00188
00189 template <class Traits>
00190 ISAInfoIF* CommonEmulator<Traits>::GetISAInfo()
00191 {
00192 return &m_alpha64Info;
00193 }
00194
00195 template <class Traits>
00196 bool CommonEmulator<Traits>::CreateProcesses( SystemIF* simSystem )
00197 {
00198 ASSERT(m_processes.empty(), "CommonEmulator<Traits>::CreateProcesses called twice.");
00199
00200 m_ProcessOpInfoCache.resize( m_processCount );
00201 m_resultCRCs.resize( m_processCount );
00202
00203 for (int i = 0; i < m_processCount; i++) {
00204 ProcessCreateParam createParam(i);
00205 ProcessState* processState = new ProcessState(i);
00206 processState->Init<Traits>( createParam, simSystem );
00207 m_processes.push_back(processState);
00208 m_ProcessOpInfoCache[i].resize( processState->GetCodeRange().second, OpInfoArray((OpInfo**)NULL, 0));
00209 }
00210
00211 return true;
00212 }
00213
00214
00215 template <class Traits>
00216 void CommonEmulator<Traits>::SetExtraOpDecoder( ExtraOpDecoderIF* extraOpDecoder )
00217 {
00218 m_extraOpDecoder = extraOpDecoder;
00219 }
00220
00221 template <class Traits>
00222 int CommonEmulator<Traits>::GetProcessCount() const
00223 {
00224 return m_processCount;
00225 }
00226
00227 template <class Traits>
00228 PC CommonEmulator<Traits>::GetEntryPoint(int pid) const
00229 {
00230 ASSERT((size_t)pid < m_processes.size());
00231 return PC(pid, TID_INVALID, m_processes[pid]->GetEntryPoint() );
00232 }
00233
00234 template <class Traits>
00235 u64 CommonEmulator<Traits>::GetInitialRegValue(int pid, int index) const
00236 {
00237 assert((size_t)pid < m_processes.size());
00238 return m_processes[pid]->GetInitialRegValue(index);
00239 }
00240
00241 template <class Traits>
00242 std::pair<OpInfo**, int> CommonEmulator<Traits>::GetOpBody(PC pc)
00243 {
00244 ProcessState* process = m_processes[pc.pid];
00245
00246
00247 const std::pair<u64, size_t> codeRange = process->GetCodeRange();
00248
00249 bool withinCodeRange = (codeRange.first <= pc.address) & (pc.address < codeRange.first+codeRange.second);
00250
00251 OpInfoArray* processOpInfoCacheEntry = NULL;
00252 if (withinCodeRange) {
00253 processOpInfoCacheEntry = &m_ProcessOpInfoCache[pc.pid][static_cast<size_t>(pc.address-codeRange.first)];
00254 if (processOpInfoCacheEntry->first != NULL)
00255 return *processOpInfoCacheEntry;
00256 }
00257
00258
00259 EmuMemAccess codeAccess( pc.address, 4 );
00260 process->GetMemorySystem()->ReadMemory( &codeAccess );
00261 u32 codeWord = (u32)codeAccess.value;
00262
00263
00264 typename CodeWordOpInfoMap::iterator e = m_codeWordToOpInfo.find(codeWord);
00265 if (e != m_codeWordToOpInfo.end()) {
00266 if (processOpInfoCacheEntry)
00267 *processOpInfoCacheEntry = e->second;
00268 return e->second;
00269 }
00270 else {
00271
00272 std::pair<ExtraOpInfoIF**, int> decodedExOps;
00273 std::vector<OpInfoType> tempOpInfo;
00274 OpInfo** opInfoArray;
00275 int nOps;
00276
00277 if( m_extraOpDecoder &&
00278 m_extraOpDecoder->Decode( codeWord, &decodedExOps )
00279 ){
00280
00281
00282
00283
00284 nOps = decodedExOps.second;
00285 opInfoArray = (OpInfo**)m_opInfoArrayPool.ordered_malloc( nOps );
00286 for( int i = 0; i < nOps; i++ ){
00287 ExtraOpInfoWrapper<ISAInfoType>* wrapper = m_exOpInfoWrapperPool.construct();
00288 wrapper->SetExtraOpInfo( decodedExOps.first[i] );
00289 opInfoArray[i] = wrapper;
00290 }
00291 }
00292 else{
00293 m_insnConverter.Convert(codeWord, back_inserter(tempOpInfo));
00294
00295
00296 nOps = (int)tempOpInfo.size();
00297 opInfoArray = (OpInfo**)m_opInfoArrayPool.ordered_malloc(nOps);
00298 for (int i = 0; i < nOps; i ++) {
00299
00300 opInfoArray[i] = m_opInfoPool.construct(tempOpInfo[i]);
00301 }
00302 }
00303
00304
00305
00306 OpInfoArray result(opInfoArray, nOps);
00307 m_codeWordToOpInfo[codeWord] = result;
00308 if (processOpInfoCacheEntry)
00309 *processOpInfoCacheEntry = result;
00310
00311 return result;
00312 }
00313 }
00314
00315 template <class Traits>
00316 std::pair<OpInfo**, int> CommonEmulator<Traits>::GetOp(PC pc)
00317 {
00318 return GetOpBody(pc);
00319 }
00320
00321 template <class Traits>
00322 MemIF* CommonEmulator<Traits>::GetMemImage()
00323 {
00324 return this;
00325 }
00326
00327 template <class Traits>
00328 void CommonEmulator<Traits>::Execute(OpStateIF* op, OpInfo* opInfoBase)
00329 {
00330 OpInfoType* opInfo = static_cast<OpInfoType*>(opInfoBase);
00331 int pid = op->GetPC().pid;
00332 ProcessState* process = m_processes[pid];
00333
00334
00335 OpEmulationState opState(op, opInfo, process);
00336 opInfo->GetEmulationFunc()(&opState);
00337 opState.ApplyEmulationState<OpInfoType>();
00338 process->GetVirtualSystem()->AddInsnTick();
00339 }
00340
00341 template <class Traits>
00342 void CommonEmulator<Traits>::Commit( OpStateIF* op, OpInfo* info )
00343 {
00344 if( m_enableResultCRC ){
00345 u64 dst = info->GetDstNum() > 0 ? op->GetDst(0) : 0;
00346 CalcCRC( op->GetPC(), dst );
00347 }
00348 }
00349
00350 template <class Traits>
00351 void CommonEmulator<Traits>::CalcCRC( const PC& pc, u64 dstResult )
00352 {
00353 m_resultCRCs[ pc.pid ].process_bytes( &pc.address , sizeof(pc.address) );
00354 m_resultCRCs[ pc.pid ].process_bytes( &dstResult , sizeof(dstResult) );
00355 }
00356
00357 template <class Traits>
00358 PC CommonEmulator<Traits>::Skip(PC pc, u64 skipCount, u64* regArray, u64* executedInsnCount, u64* executedOpCount)
00359 {
00360 if (skipCount == 0) {
00361 if (executedInsnCount)
00362 *executedInsnCount = 0;
00363 if (executedOpCount)
00364 *executedOpCount = 0;
00365 return pc;
00366 }
00367
00368 u64 totalOpCount = 0;
00369 u64 initialSkipCount = skipCount;
00370 ProcessState* process = m_processes[pc.pid];
00371 VirtualSystem* virtualSystem = process->GetVirtualSystem();
00372 bool enableResultCRC = m_enableResultCRC;
00373
00374 SkipOp op(this);
00375 while (skipCount-- != 0 && pc.address != 0) {
00376 std::pair<OpInfo**, int> ops_pair = GetOpBody(pc);
00377 OpInfo** opInfoArray = ops_pair.first;
00378 int opCount = ops_pair.second;
00379
00380
00381 for (int opIndex = 0; opIndex < opCount; opIndex ++) {
00382 totalOpCount++;
00383 OpInfoType* opInfo = static_cast<OpInfoType*>( opInfoArray[opIndex] );
00384
00385 OpEmulationState opState(&op, opInfo, process, pc, pc.address + ISAInfoType::InstructionWordBitSize/8, regArray);
00386 opInfo->GetEmulationFunc()(&opState);
00387 opState.ApplyEmulationStateToRegArray<OpInfoType>(regArray);
00388
00389 if( enableResultCRC ){
00390 u64 dst = opInfo->GetDstNum() > 0 ? opState.GetDst(0) : 0;
00391 CalcCRC( pc, dst );
00392 }
00393 virtualSystem->AddInsnTick();
00394
00395 if (opIndex == opCount-1) {
00396 if (opState.GetTaken())
00397 pc.address = opState.GetTakenPC();
00398 else
00399 pc.address += ISAInfoType::InstructionWordBitSize/8;
00400 break;
00401 }
00402 }
00403 }
00404
00405 if (executedInsnCount)
00406 *executedInsnCount = initialSkipCount - skipCount;
00407 if (executedOpCount)
00408 *executedOpCount = totalOpCount;
00409 return pc;
00410 }
00411
00412 template <class Traits>
00413 void CommonEmulator<Traits>::Read( MemAccess* access )
00414 {
00415 int pid = access->address.pid;
00416 ProcessState* process = m_processes[pid];
00417 process->GetMemorySystem()->ReadMemory(access);
00418 }
00419
00420 template <class Traits>
00421 void CommonEmulator<Traits>::Write( MemAccess* access )
00422 {
00423 int pid = access->address.pid;
00424 ProcessState* process = m_processes[pid];
00425 process->GetMemorySystem()->WriteMemory(access);
00426 }
00427
00428 }
00429 }
00430
00431 #endif
00432