src/Emu/Utility/CommonEmulator.h

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
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         // G~[^
00057         template <class Traits>
00058         class CommonEmulator : 
00059             public EmulatorIF,
00060             public MemIF, 
00061             public ParamExchange
00062         {
00063         private:
00064             // Traits C^typedef\
00065             // ^eVXe^`CeVXepG~[^`
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             // ParamExchange 
00078             using ParamExchangeType::LoadParam;
00079             using ParamExchangeType::ReleaseParam;
00080             using ParamExchangeType::GetRootPath;
00081             using ParamExchangeType::ParamEntry;
00082 
00083             // EmulatorIF タ
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             // MemIF タ
00096             virtual void Read( MemAccess* access );
00097             virtual void Write( MemAccess* access );
00098 
00099         private:
00100             bool CreateProcesses( SystemIF* simSystem );
00101             
00102             // o[`タ
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             //  OpInfo LbV
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             // AhXCAhXOpInfo
00123             typedef std::pair<OpInfo**, int> OpInfoArray;
00124             std::vector< std::vector< OpInfoArray > > m_ProcessOpInfoCache;
00125             // CopInfoArray OpInfo|C^|C^ OpInfo 
00126             typedef unordered_map<u32, OpInfoArray, CodeWordHash> CodeWordOpInfoMap;
00127             CodeWordOpInfoMap m_codeWordToOpInfo;
00128 
00129             // param_map
00130             int m_processCount;
00131             
00132             // OfR[_
00133             ExtraOpDecoderIF* m_extraOpDecoder;
00134 
00135             // CRCs of PCs and results of all retired ops.
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             // param, vZX
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         // OfR[_Zbg
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             // vZXLbV
00247             const std::pair<u64, size_t> codeRange = process->GetCodeRange();
00248             // ZI] &&  & gp
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             // L[LbV
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                 // s
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                     // OfR[_fR[hsC
00281                     // ExtraOpInfoWrapper fR[hi[
00282 
00283                     // i[|C^z opInfoArrayPool m
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                     // i[|C^z opInfoArrayPool m
00296                     nOps = (int)tempOpInfo.size();
00297                     opInfoArray = (OpInfo**)m_opInfoArrayPool.ordered_malloc(nOps);
00298                     for (int i = 0; i < nOps; i ++) {
00299                         // opInfoPool   opInfo Rs[CopInfoArray i[
00300                         opInfoArray[i] = m_opInfoPool.construct(tempOpInfo[i]);
00301                     }
00302                 }
00303 
00304 
00305                 // LbVi[
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             // タs
00335             OpEmulationState opState(op, opInfo, process);  // opIyh OpEmulationState \z
00336             opInfo->GetEmulationFunc()(&opState);
00337             opState.ApplyEmulationState<OpInfoType>();  // op l
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                 // opInfoArray Sタs
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);   // opIyh OpEmulationState \z
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     } // namespace EmulatorUtility
00429 } // namespace Onikiri
00430 
00431 #endif
00432 

Onikiri2に対してTue Jun 18 14:34:20 2013に生成されました。  doxygen 1.4.7