src/Emu/Utility/GenericOperation.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_EMULATORUTILITY_GENERIC_OPERATION_H
00033 #define EMU_UTILITY_EMULATORUTILITY_GENERIC_OPERATION_H
00034 
00035 #include "SysDeps/fenv.h"
00036 #include "Emu/Utility/Math.h"
00037 #include "Emu/Utility/OpEmulationState.h"
00038 
00039 namespace Onikiri {
00040 namespace EmulatorUtility {
00041 namespace Operation {
00042 
00043 // 
00044 
00045 // high-order 64 bits of the 128-bit product of unsigned lhs and rhs
00046 u64 UnsignedMulHigh64(u64 lhs, u64 rhs);
00047 // high-order 64 bits of the 128-bit product of signed lhs and rhs
00048 s64 SignedMulHigh64(s64 lhs, s64 rhs);
00049 
00050 typedef u64 RegisterType;
00051 
00052 // DestK
00053 // DestDestliDestVKPhyRegS~j
00054 
00055 // interface
00056 inline void do_branch(OpEmulationState* opState, u64 target)
00057 {
00058     opState->SetTaken(true);
00059 }
00060 
00061 inline u64 next_pc(OpEmulationState* opState)
00062 {
00063     return opState->GetPC()+4;
00064 }
00065 
00066 inline u64 current_pc(OpEmulationState* opState)
00067 {
00068     return opState->GetPC();
00069 }
00070 
00071 template <typename T>
00072 inline void WriteMemory(OpEmulationState* opState, u64 addr, const T &value)
00073 {
00074     Onikiri::MemAccess access;
00075     access.address.pid = opState->GetPID();
00076     access.address.address = addr;
00077     access.size = sizeof(T);
00078     access.sign = false;
00079     access.value = value;
00080     opState->GetOpState()->Write( &access );
00081 }
00082 
00083 template <typename T>
00084 inline T ReadMemory(OpEmulationState* opState, u64 addr)
00085 {
00086     Onikiri::MemAccess access;
00087     access.address.pid = opState->GetPID();
00088     access.address.address = addr;
00089     access.size = sizeof(T);
00090     access.sign = false;
00091     access.value = 0;
00092     opState->GetOpState()->Read( &access );
00093     return static_cast<T>( access.value );
00094 }
00095 
00096 
00097 // utility
00098 
00099 // ^valueCrbg\_^
00100 template <typename FPType, typename IntType>
00101 inline FPType AsFPFunc(IntType value)
00102 {
00103     BOOST_STATIC_ASSERT(sizeof(IntType) == sizeof(FPType));
00104 
00105     union {
00106         IntType i;
00107         FPType  f;
00108     } intfp;
00109 
00110     intfp.i = value;
00111     return intfp.f;
00112 }
00113 
00114 // _^valueCrbg\^
00115 template <typename IntType, typename FPType>
00116 inline IntType AsIntFunc(FPType value)
00117 {
00118     BOOST_STATIC_ASSERT(sizeof(IntType) == sizeof(FPType));
00119     union {
00120         IntType i;
00121         FPType  f;
00122     } intfp;
00123 
00124     intfp.f = value;
00125     return intfp.i;
00126 }
00127 
00128 // rbg_゚ ( reinterpret as fp )
00129 template <typename Type, typename TSrc>
00130 struct AsFP : public std::unary_function<OpEmulationState*, Type>
00131 {
00132     Type operator()(OpEmulationState* opState)
00133     {
00134         return AsFPFunc<Type>( TSrc()(opState) );
00135     }
00136 };
00137 
00138 // _rbg゚ ( reinterpret as int )
00139 template <typename Type, typename TSrc>
00140 struct AsInt : public std::unary_function<OpEmulationState*, Type>
00141 {
00142     Type operator()(OpEmulationState* opState)
00143     {
00144         return AsFPFunc<Type>( TSrc()(opState) );
00145     }
00146 };
00147 
00148 // **********************************
00149 // operands
00150 // **********************************
00151 
00152 // operand unsignedl
00153 
00154 template <int OperandIndex>
00155 class DstOperand
00156 {
00157 public:
00158     typedef RegisterType type;
00159     static void SetOperand(OpEmulationState* opState, RegisterType value)
00160     {
00161         opState->SetDst(OperandIndex, value);
00162     }
00163 };
00164 
00165 template <int OperandIndex>
00166 struct SrcOperand : public std::unary_function<OpEmulationState, RegisterType>
00167 {
00168     typedef RegisterType type;
00169     RegisterType operator()(OpEmulationState* opState)
00170     {
00171         return opState->GetSrc(OperandIndex);
00172     }
00173 };
00174 
00175 template <typename Type, Type value>
00176 struct IntConst : public std::unary_function<OpEmulationState*, Type>
00177 {
00178     Type operator()(OpEmulationState* opState)
00179     {
00180         return value;
00181     }
00182 };
00183 
00184 // **********************************
00185 // conditions
00186 // **********************************
00187 
00188 //
00189 // integer conditions
00190 //
00191 template<typename Type, typename ArgType = RegisterType>
00192 struct IntCondEqual : public std::binary_function<ArgType, ArgType, bool>
00193 {
00194     bool operator()(const ArgType lhs, const ArgType rhs) const
00195     {
00196         return static_cast<Type>(lhs) == static_cast<Type>(rhs);
00197     }
00198 };
00199 
00200 template<typename Type, typename ArgType = RegisterType>
00201 struct IntCondNotEqual : public std::binary_function<ArgType, ArgType, bool>
00202 {
00203     bool operator()(const ArgType lhs, const ArgType rhs) const
00204     {
00205         return static_cast<Type>(lhs) != static_cast<Type>(rhs);
00206     }
00207 };
00208 
00209 template<typename Type, typename ArgType = RegisterType>
00210 struct IntCondLessSigned : public std::binary_function<ArgType, ArgType, bool>
00211 {
00212     bool operator()(const ArgType lhs, const ArgType rhs) const
00213     {
00214         return cast_to_signed(static_cast<Type>(lhs)) < cast_to_signed(static_cast<Type>(rhs));
00215     }
00216 };
00217 
00218 template<typename Type, typename ArgType = RegisterType>
00219 struct IntCondLessUnsigned : public std::binary_function<ArgType, ArgType, bool>
00220 {
00221     bool operator()(const ArgType lhs, const ArgType rhs) const
00222     {
00223         return cast_to_unsigned(static_cast<Type>(lhs)) < cast_to_unsigned(static_cast<Type>(rhs));
00224     }
00225 };
00226 
00227 template<typename Type, typename ArgType = RegisterType>
00228 struct IntCondLessEqualSigned : public std::binary_function<ArgType, ArgType, bool>
00229 {
00230     bool operator()(const ArgType lhs, const ArgType rhs) const
00231     {
00232         return cast_to_signed(static_cast<Type>(lhs)) <= cast_to_signed(static_cast<Type>(rhs));
00233     }
00234 };
00235 
00236 template<typename Type, typename ArgType = RegisterType>
00237 struct IntCondLessEqualUnsigned : public std::binary_function<ArgType, ArgType, bool>
00238 {
00239     bool operator()(const ArgType lhs, const ArgType rhs) const
00240     {
00241         return cast_to_unsigned(static_cast<Type>(lhs)) <= cast_to_unsigned(static_cast<Type>(rhs));
00242     }
00243 };
00244 
00245 template<typename Type, typename ArgType = RegisterType>
00246 struct IntCondGreaterSigned : public std::binary_function<ArgType, ArgType, bool>
00247 {
00248     bool operator()(const ArgType lhs, const ArgType rhs) const
00249     {
00250         return cast_to_signed(static_cast<Type>(lhs)) > cast_to_signed(static_cast<Type>(rhs));
00251     }
00252 };
00253 
00254 template<typename Type, typename ArgType = RegisterType>
00255 struct IntCondGreaterUnsigned : public std::binary_function<ArgType, ArgType, bool>
00256 {
00257     bool operator()(const ArgType lhs, const ArgType rhs) const
00258     {
00259         return cast_to_unsigned(static_cast<Type>(lhs)) > cast_to_unsigned(static_cast<Type>(rhs));
00260     }
00261 };
00262 
00263 template<typename Type, typename ArgType = RegisterType>
00264 struct IntCondGreaterEqualSigned : public std::binary_function<ArgType, ArgType, bool>
00265 {
00266     bool operator()(const ArgType lhs, const ArgType rhs) const
00267     {
00268         return cast_to_signed(static_cast<Type>(lhs)) >= cast_to_signed(static_cast<Type>(rhs));
00269     }
00270 };
00271 
00272 template<typename Type, typename ArgType = RegisterType>
00273 struct IntCondGreaterEqualUnsigned : public std::binary_function<ArgType, ArgType, bool>
00274 {
00275     bool operator()(const ArgType lhs, const ArgType rhs) const
00276     {
00277         return cast_to_unsigned(static_cast<Type>(lhs)) >= cast_to_unsigned(static_cast<Type>(rhs));
00278     }
00279 };
00280 
00281 template<typename Type, int n, typename ArgType = RegisterType>
00282 struct IntCondEqualNthBit : public std::binary_function<ArgType, ArgType, bool>
00283 {
00284     bool operator()(const ArgType lhs, const ArgType rhs) const
00285     {
00286         return (static_cast<Type>(lhs) & ((Type)1 << n)) == (static_cast<Type>(rhs) & ((Type)1 << n));
00287     }
00288 };
00289 
00290 template<typename Type, int n, typename ArgType = RegisterType>
00291 struct IntCondNotEqualNthBit : public std::binary_function<ArgType, ArgType, bool>
00292 {
00293     bool operator()(const ArgType lhs, const ArgType rhs) const
00294     {
00295         return (static_cast<Type>(lhs) & ((Type)1 << n)) != (static_cast<Type>(rhs) & ((Type)1 << n));
00296     }
00297 };
00298 
00299 //
00300 // fp conditions
00301 //
00302 template<typename Type, typename ArgType = RegisterType>
00303 struct FPCondEqual : public std::binary_function<ArgType, ArgType, bool>
00304 {
00305     bool operator()(const ArgType lhs, const ArgType rhs) const
00306     {
00307         return AsFPFunc<Type>(lhs) == AsFPFunc<Type>(rhs);
00308     }
00309 };
00310 
00311 template<typename Type, typename ArgType = RegisterType>
00312 struct FPCondNotEqual : public std::binary_function<ArgType, ArgType, bool>
00313 {
00314     bool operator()(const ArgType lhs, const ArgType rhs) const
00315     {
00316         return AsFPFunc<Type>(lhs) != AsFPFunc<Type>(rhs);
00317     }
00318 };
00319 
00320 template<typename Type, typename ArgType = RegisterType>
00321 struct FPCondLess : public std::binary_function<ArgType, ArgType, bool>
00322 {
00323     bool operator()(const ArgType lhs, const ArgType rhs) const
00324     {
00325         return AsFPFunc<Type>(lhs) < AsFPFunc<Type>(rhs);
00326     }
00327 };
00328 
00329 template<typename Type, typename ArgType = RegisterType>
00330 struct FPCondLessEqual : public std::binary_function<ArgType, ArgType, bool>
00331 {
00332     bool operator()(const ArgType lhs, const ArgType rhs) const
00333     {
00334         return AsFPFunc<Type>(lhs) <= AsFPFunc<Type>(rhs);
00335     }
00336 };
00337 
00338 template<typename Type, typename ArgType = RegisterType>
00339 struct FPCondGreater : public std::binary_function<ArgType, ArgType, bool>
00340 {
00341     bool operator()(const ArgType lhs, const ArgType rhs) const
00342     {
00343         return AsFPFunc<Type>(lhs) > AsFPFunc<Type>(rhs);
00344     }
00345 };
00346 
00347 template<typename Type, typename ArgType = RegisterType>
00348 struct FPCondGreaterEqual : public std::binary_function<ArgType, ArgType, bool>
00349 {
00350     bool operator()(const ArgType lhs, const ArgType rhs) const
00351     {
00352         return AsFPFunc<Type>(lhs) >= AsFPFunc<Type>(rhs);
00353     }
00354 };
00355 
00356 template <typename TSrc1, typename TSrc2>
00357 struct CondAnd : public std::unary_function<OpEmulationState*, bool>
00358 {
00359     bool operator()(OpEmulationState* opState)
00360     {
00361         bool lhs = TSrc1()(opState) != 0;
00362         bool rhs = TSrc2()(opState) != 0;
00363 
00364         return lhs && rhs;
00365     }
00366 };
00367 
00368 template <typename TSrc1, typename TSrc2>
00369 struct CondOr : public std::unary_function<OpEmulationState*, bool>
00370 {
00371     bool operator()(OpEmulationState* opState)
00372     {
00373         bool lhs = TSrc1()(opState) != 0;
00374         bool rhs = TSrc2()(opState) != 0;
00375 
00376         return lhs || rhs;
00377     }
00378 };
00379 
00380 // **********************************
00381 // operations
00382 // **********************************
00383 inline void UndefinedOperation(OpEmulationState* opState)
00384 {
00385     // do nothing
00386     // opState->undef = true ?
00387 }
00388 
00389 
00390 inline void NoOperation(OpEmulationState* opState)
00391 {
00392     // no operation
00393 }
00394 
00395 // Func1, Func2, ... PA
00396 template <
00397     void (*Func1)(OpEmulationState *),
00398     void (*Func2)(OpEmulationState *)
00399 >
00400 inline void Sequence2(OpEmulationState* opState)
00401 {
00402     Func1(opState);
00403     Func2(opState);
00404 }
00405 
00406 template <
00407     void (*Func1)(OpEmulationState *),
00408     void (*Func2)(OpEmulationState *),
00409     void (*Func3)(OpEmulationState *)
00410 >
00411 inline void Sequence3(OpEmulationState* opState)
00412 {
00413     Func1(opState);
00414     Func2(opState);
00415     Func3(opState);
00416 }
00417 
00418 // **********************************
00419 //    result setting
00420 // **********************************
00421 template <typename TDest, typename TFunc>
00422 inline void SetSext(OpEmulationState* opState)
00423 {
00424     TDest::SetOperand(opState, cast_to_signed( TFunc()(opState) ) );
00425 }
00426 
00427 template <typename TDest, typename TFunc>
00428 inline void Set(OpEmulationState* opState)
00429 {
00430     TDest::SetOperand(opState, TFunc()(opState) );
00431 }
00432 
00433 template <typename TDest, typename TFunc>
00434 inline void SetFP(OpEmulationState* opState)
00435 {
00436     TDest::SetOperand(opState, AsIntFunc<RegisterType>( TFunc()(opState) ) );
00437 }
00438 
00439 template <typename Type, typename TCond, typename TTrueValue, typename TFalseValue>
00440 struct Select : public std::unary_function<OpEmulationState*, Type>
00441 {
00442     Type operator()(OpEmulationState* opState)
00443     {
00444         if ( TCond()(opState) ) {
00445             return TTrueValue()(opState);
00446         }
00447         else {
00448             return TFalseValue()(opState);
00449         }
00450     }
00451 };
00452 
00453 // TValue  Type 
00454 template <typename Type, typename TValue>
00455 struct Cast : public std::unary_function<OpEmulationState*, Type>
00456 {
00457     Type operator()(OpEmulationState* opState)
00458     {
00459         return static_cast<Type>( TValue()(opState) );
00460     }
00461 };
00462 
00463 // [hw TValue  Type D
00464 template <typename Type, typename TValue, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
00465 struct CastFP : public std::unary_function<OpEmulationState*, Type>
00466 {
00467     Type operator()(OpEmulationState* opState)
00468     {
00469         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
00470         volatile Type rvalue = static_cast<Type>( TValue()(opState) );
00471         return rvalue;
00472     }
00473 };
00474 
00475 // **********************************
00476 //    memory operations
00477 // **********************************
00478 template <typename Type, typename TAddr>
00479 struct Load : public std::unary_function<OpEmulationState*, Type>
00480 {
00481     Type operator()(OpEmulationState* opState)
00482     {
00483         return ReadMemory<Type>( opState, TAddr()(opState) );
00484     }
00485 };
00486 
00487 template <typename Type, typename TValue, typename TAddr>
00488 inline void Store(OpEmulationState* opState)
00489 {
00490     WriteMemory<Type>(opState, TAddr()(opState), static_cast<Type>( TValue()(opState) ));
00491 }
00492 
00493 
00494 // **********************************
00495 //    int arithmetic operations
00496 // **********************************
00497 
00498 template <typename Type, typename TSrc1, typename TSrc2>
00499 struct IntAdd : public std::unary_function<OpEmulationState*, Type>
00500 {
00501     Type operator()(OpEmulationState* opState)
00502     {
00503         return static_cast<Type>(TSrc1()(opState)) + static_cast<Type>(TSrc2()(opState));
00504     }
00505 };
00506 
00507 template <typename Type, typename TSrc1, typename TSrc2>
00508 struct IntSub : public std::unary_function<OpEmulationState*, Type>
00509 {
00510     Type operator()(OpEmulationState* opState)
00511     {
00512         return static_cast<Type>(TSrc1()(opState)) - static_cast<Type>(TSrc2()(opState));
00513     }
00514 };
00515 
00516 template <typename Type, typename TSrc1, typename TSrc2>
00517 struct IntMul : public std::unary_function<OpEmulationState*, Type>
00518 {
00519     Type operator()(OpEmulationState* opState)
00520     {
00521         return static_cast<Type>(TSrc1()(opState)) * static_cast<Type>(TSrc2()(opState));
00522     }
00523 };
00524 
00525 template <typename Type, typename TSrc1, typename TSrc2>
00526 struct IntDiv : public std::unary_function<OpEmulationState*, Type>
00527 {
00528     Type operator()(OpEmulationState* opState)
00529     {
00530         Type src2 = static_cast<Type>(TSrc2()(opState));
00531         if( src2 == 0 ){
00532             u64 addr = opState->GetOpState()->GetPC().address;
00533             RUNTIME_WARNING( 
00534                 "Division by zero occurred and returned 0 at PC: %08x%08x", 
00535                 (u32)(addr >> 32),
00536                 (u32)(addr & 0xffffffff)
00537             );
00538             return 0;
00539         }
00540         return static_cast<Type>(TSrc1()(opState)) / static_cast<Type>(TSrc2()(opState));
00541     }
00542 };
00543 
00544 // Src1  shift_countVtgZ
00545 template <typename Type, int shift_count, typename TSrc1, typename TSrc2>
00546 struct IntScaledAdd : public std::unary_function<OpEmulationState*, Type>
00547 {
00548     Type operator()(OpEmulationState* opState)
00549     {
00550         return (static_cast<Type>(TSrc1()(opState)) << shift_count) + static_cast<Type>(TSrc2()(opState));
00551     }
00552 };
00553 
00554 // Src1  shift_countVtgZ
00555 template <typename Type, int shift_count, typename TSrc1, typename TSrc2>
00556 struct IntScaledSub : public std::unary_function<OpEmulationState*, Type>
00557 {
00558     Type operator()(OpEmulationState* opState)
00559     {
00560         return (static_cast<Type>(TSrc1()(opState)) << shift_count) - static_cast<Type>(TSrc2()(opState));
00561     }
00562 };
00563 
00564 // compare
00565 template <typename TSrc1, typename TSrc2, typename Comp>
00566 struct Compare : public std::unary_function<OpEmulationState*, bool>
00567 {
00568     bool operator()(OpEmulationState* opState)
00569     {
00570         return Comp()(TSrc1()(opState), TSrc2()(opState));
00571     }
00572 };
00573 
00574 // negate
00575 template <typename Type, typename TSrc1>
00576 struct IntNeg : public std::unary_function<OpEmulationState*, Type>
00577 {
00578     Type operator()(OpEmulationState* opState)
00579     {
00580         return cast_to_unsigned( -cast_to_signed( static_cast<Type>( TSrc1()(opState) ) ) );
00581     }
00582 };
00583 
00584 // Type must be unsigned
00585 template <typename Type, typename TSrc1, typename TSrc2>
00586 struct CarryOfAdd : public std::unary_function<OpEmulationState*, RegisterType>
00587 {
00588     RegisterType operator()(OpEmulationState* opState)
00589     {
00590         Type lhs = static_cast<Type>( TSrc1()(opState) );
00591         Type rhs = static_cast<Type>( TSrc2()(opState) );
00592 
00593         if (lhs + rhs < rhs)
00594             return 1;
00595         else
00596             return 0;
00597     }
00598 };
00599 
00600 // Type must be unsigned
00601 template <typename Type, typename TSrc1, typename TSrc2, typename TSrcCarry>
00602 struct CarryOfAddWithCarry : public std::unary_function<OpEmulationState*, RegisterType>
00603 {
00604     RegisterType operator()(OpEmulationState* opState)
00605     {
00606         Type lhs = static_cast<Type>( TSrc1()(opState) );
00607         Type rhs = static_cast<Type>( TSrc2()(opState) );
00608         Type carry = static_cast<Type>( TSrcCarry()(opState) );
00609 
00610         ASSERT(carry == 0 || carry == 1);
00611 
00612         if (lhs + rhs < rhs || lhs + rhs + carry < rhs) // lhs, rhs ~0 lhs + rhs + 1 < rhs  (ex. 255 + 255 + 1 = 255)
00613             return 1;
00614         else
00615             return 0;
00616     }
00617 };
00618 
00619 // Type must be unsigned
00620 template <typename Type, typename TSrc1, typename TSrc2>
00621 struct BorrowOfSub : public std::unary_function<OpEmulationState*, RegisterType>
00622 {
00623     RegisterType operator()(OpEmulationState* opState)
00624     {
00625         Type lhs = static_cast<Type>( TSrc1()(opState) );
00626         Type rhs = static_cast<Type>( TSrc2()(opState) );
00627 
00628         if (lhs < rhs)
00629             return 1;
00630         else
00631             return 0;
00632     }
00633 };
00634 
00635 // Type must be unsigned
00636 template <typename Type, typename TSrc1, typename TSrc2, typename TSrcBorrow>
00637 struct BorrowOfSubWithBorrow : public std::unary_function<OpEmulationState*, RegisterType>
00638 {
00639     RegisterType operator()(OpEmulationState* opState)
00640     {
00641         Type lhs = static_cast<Type>( TSrc1()(opState) );
00642         Type rhs = static_cast<Type>( TSrc2()(opState) );
00643         Type borrow = static_cast<Type>( TSrcBorrow()(opState) );
00644 
00645         ASSERT(borrow == 0 || borrow == 1);
00646 
00647         if (rhs == ~(Type)0 || lhs < rhs + borrow)
00648             return 1;
00649         else
00650             return 0;
00651     }
00652 };
00653 
00654 template <typename TSrc1, typename TSrc2>
00655 struct IntUMulh64 : public std::unary_function<EmulatorUtility::OpEmulationState, u64>
00656 {
00657     u64 operator()(OpEmulationState* opState) const
00658     {
00659         u64 lhs = TSrc1()(opState);
00660         u64 rhs = TSrc2()(opState);
00661 
00662         return UnsignedMulHigh64(lhs, rhs);
00663     }
00664 };
00665 
00666 template <typename TSrc1, typename TSrc2>
00667 struct IntSMulh64 : public std::unary_function<EmulatorUtility::OpEmulationState, u64>
00668 {
00669     s64 operator()(OpEmulationState* opState) const
00670     {
00671         s64 lhs = static_cast<s64>(TSrc1()(opState));
00672         s64 rhs = static_cast<s64>(TSrc2()(opState));
00673 
00674         return SignedMulHigh64(lhs, rhs);
00675     }
00676 };
00677 
00678 // **********************************
00679 //    shift operations
00680 // **********************************
00681 
00682 // arithmetic right shift
00683 template <typename Type, typename TSrc1, typename TSrc2, unsigned int count_mask>
00684 struct AShiftR : public std::unary_function<OpEmulationState*, Type>
00685 {
00686     Type operator()(OpEmulationState* opState)
00687     {
00688         Type value = static_cast<Type>( TSrc1()(opState) );
00689         typename TSrc2::result_type count = static_cast<typename TSrc2::result_type>( TSrc2()(opState) ) & count_mask;
00690         
00691         if (count >= sizeof(Type)*8)
00692             return 0;
00693         else
00694             return static_cast<Type>( cast_to_unsigned( cast_to_signed(value) >> count ) );
00695     }
00696 };
00697 
00698 // logical right shift
00699 template <typename Type, typename TSrc1, typename TSrc2, unsigned int count_mask>
00700 struct LShiftR : public std::unary_function<OpEmulationState*, Type>
00701 {
00702     Type operator()(OpEmulationState* opState)
00703     {
00704         Type value = static_cast<Type>( TSrc1()(opState) );
00705         typename TSrc2::result_type count = static_cast<typename TSrc2::result_type>( TSrc2()(opState) ) & count_mask;
00706         
00707         if (count >= sizeof(Type)*8)
00708             return 0;
00709         else
00710             return static_cast<Type>( cast_to_unsigned( cast_to_unsigned(value) >> count ) );
00711     }
00712 };
00713 // logical left shift
00714 template <typename Type, typename TSrc1, typename TSrc2, unsigned int count_mask>
00715 struct LShiftL : public std::unary_function<OpEmulationState*, Type>
00716 {
00717     Type operator()(OpEmulationState* opState)
00718     {
00719         Type value = static_cast<Type>( TSrc1()(opState) );
00720         typename TSrc2::result_type count = static_cast<typename TSrc2::result_type>( TSrc2()(opState) ) & count_mask;
00721         
00722         if (count >= sizeof(Type)*8)
00723             return 0;
00724         else
00725             return static_cast<Type>( cast_to_unsigned( cast_to_unsigned(value) << count ) );
00726     }
00727 };
00728 
00729 // rotate left
00730 template <typename Type, typename TSrcValue, typename TSrcCount>
00731 struct RotateL : public std::unary_function<OpEmulationState*, Type>
00732 {
00733     Type operator()(OpEmulationState* opState)
00734     {
00735         const int typeBitCount = sizeof(Type)*8;
00736         Type value = static_cast<Type>( TSrcValue()(opState) );
00737         int count = static_cast<int>( TSrcCount()(opState) & (typeBitCount-1) );
00738 
00739         if (count == 0)
00740             return value;
00741         else
00742             return (value << count) | (value >> (typeBitCount-count));
00743     }
00744 };
00745 
00746 template <typename Type, typename TSrcValue, typename TSrcCount>
00747 struct RotateR : public std::unary_function<OpEmulationState*, Type>
00748 {
00749     Type operator()(OpEmulationState* opState)
00750     {
00751         const int typeBitCount = sizeof(Type)*8;
00752         Type value = static_cast<Type>( TSrcValue()(opState) );
00753         int count = static_cast<int>( TSrcCount()(opState) & (typeBitCount-1) );
00754 
00755         if (count == 0)
00756             return value;
00757         else
00758             return (value >> count) | (value << (typeBitCount-count));
00759     }
00760 };
00761 
00762 
00763 // **********************************
00764 //    logical operations
00765 // **********************************
00766 
00767 // and, or, xor, ... C++\ (\L)
00768 
00769 // src1 & src2
00770 template <typename Type, typename TSrc1, typename TSrc2>
00771 struct BitAnd : public std::unary_function<OpEmulationState*, Type>
00772 {
00773     Type operator()(OpEmulationState* opState)
00774     {
00775         Type lhs = static_cast<Type>( TSrc1()(opState) );
00776         Type rhs = static_cast<Type>( TSrc2()(opState) );
00777 
00778         return lhs & rhs;
00779     }
00780 };
00781 
00782 
00783 // src1 & ~src2
00784 template <typename Type, typename TSrc1, typename TSrc2>
00785 struct BitAndNot : public std::unary_function<OpEmulationState*, Type>
00786 {
00787     Type operator()(OpEmulationState* opState)
00788     {
00789         Type lhs = static_cast<Type>( TSrc1()(opState) );
00790         Type rhs = static_cast<Type>( TSrc2()(opState) );
00791 
00792         return lhs & ~rhs;
00793     }
00794 };
00795 
00796 // ~(src1 & src2)
00797 template <typename Type, typename TSrc1, typename TSrc2>
00798 struct BitNand : public std::unary_function<OpEmulationState*, Type>
00799 {
00800     Type operator()(OpEmulationState* opState)
00801     {
00802         Type lhs = static_cast<Type>( TSrc1()(opState) );
00803         Type rhs = static_cast<Type>( TSrc2()(opState) );
00804 
00805         return ~(lhs & rhs);
00806     }
00807 };
00808 
00809 // src1 | src2
00810 template <typename Type, typename TSrc1, typename TSrc2>
00811 struct BitOr : public std::unary_function<OpEmulationState*, Type>
00812 {
00813     Type operator()(OpEmulationState* opState)
00814     {
00815         Type lhs = static_cast<Type>( TSrc1()(opState) );
00816         Type rhs = static_cast<Type>( TSrc2()(opState) );
00817 
00818         return lhs | rhs;
00819     }
00820 };
00821 
00822 // src1 | ~src2
00823 template <typename Type, typename TSrc1, typename TSrc2>
00824 struct BitOrNot : public std::unary_function<OpEmulationState*, Type>
00825 {
00826     Type operator()(OpEmulationState* opState)
00827     {
00828         Type lhs = static_cast<Type>( TSrc1()(opState) );
00829         Type rhs = static_cast<Type>( TSrc2()(opState) );
00830 
00831         return lhs | ~rhs;
00832     }
00833 };
00834 
00835 // ~(src1 | src2)
00836 template <typename Type, typename TSrc1, typename TSrc2>
00837 struct BitNor : public std::unary_function<OpEmulationState*, Type>
00838 {
00839     Type operator()(OpEmulationState* opState)
00840     {
00841         Type lhs = static_cast<Type>( TSrc1()(opState) );
00842         Type rhs = static_cast<Type>( TSrc2()(opState) );
00843 
00844         return ~(lhs | rhs);
00845     }
00846 };
00847 
00848 // src1 ^ src2
00849 template <typename Type, typename TSrc1, typename TSrc2>
00850 struct BitXor : public std::unary_function<OpEmulationState*, Type>
00851 {
00852     Type operator()(OpEmulationState* opState)
00853     {
00854         Type lhs = static_cast<Type>( TSrc1()(opState) );
00855         Type rhs = static_cast<Type>( TSrc2()(opState) );
00856 
00857         return lhs ^ rhs;
00858     }
00859 };
00860 
00861 // eqv
00862 template <typename Type, typename TSrc1, typename TSrc2>
00863 struct BitXorNot : public std::unary_function<OpEmulationState*, Type>
00864 {
00865     Type operator()(OpEmulationState* opState)
00866     {
00867         Type lhs = static_cast<Type>( TSrc1()(opState) );
00868         Type rhs = static_cast<Type>( TSrc2()(opState) );
00869 
00870         return lhs ^ ~rhs;
00871     }
00872 };
00873 
00874 template <typename Type, typename TSrc1>
00875 struct BitNot : public std::unary_function<OpEmulationState*, Type>
00876 {
00877     Type operator()(OpEmulationState* opState)
00878     {
00879         Type lhs = static_cast<Type>( TSrc1()(opState) );
00880 
00881         return ~lhs;
00882     }
00883 };
00884 
00885 template <typename Type, typename TSrc, typename TBegin, typename TCount>
00886 struct BitExtract : public std::unary_function<OpEmulationState*, Type>
00887 {
00888     Type operator()(OpEmulationState* opState)
00889     {
00890         Type value = static_cast<Type>( TSrc()(opState) );
00891 
00892         return (value >> (size_t)TBegin()(opState)) & shttl::mask(0, (size_t)TCount()(opState));
00893     }
00894 };
00895 
00896 // **********************************
00897 //    counting zero operations
00898 // **********************************
00899 template <typename Type, typename TSrc>
00900 struct NumberOfPopulations : public std::unary_function<OpEmulationState*, Type>
00901 {
00902     Type operator()(OpEmulationState* opState)
00903     {
00904         u64 value = static_cast<u64>( TSrc()(opState));
00905 
00906         value = (value & 0x55555555) + (value >> 1 & 0x55555555);
00907         value = (value & 0x33333333) + (value >> 2 & 0x33333333);
00908         value = (value & 0x0f0f0f0f) + (value >> 4 & 0x0f0f0f0f);
00909         value = (value & 0x00ff00ff) + (value >> 8 & 0x00ff00ff);
00910         return static_cast<Type>((value & 0x0000ffff) + (value >>16 & 0x0000ffff));
00911     }
00912 };
00913 
00914 template <typename Type, typename TSrc>
00915 struct NumberOfLeadingZeros : public std::unary_function<OpEmulationState*, Type>
00916 {
00917     Type operator()(OpEmulationState* opState)
00918     {
00919         u64 value = static_cast<u64>( TSrc()(opState));
00920 
00921         value |= (value >> 1);
00922         value |= (value >> 2);
00923         value |= (value >> 4);
00924         value |= (value >> 8);
00925         value |= (value >> 16);
00926 
00927         value = ~value;
00928 
00929         value = (value & 0x55555555) + (value >> 1 & 0x55555555);
00930         value = (value & 0x33333333) + (value >> 2 & 0x33333333);
00931         value = (value & 0x0f0f0f0f) + (value >> 4 & 0x0f0f0f0f);
00932         value = (value & 0x00ff00ff) + (value >> 8 & 0x00ff00ff);
00933         return static_cast<Type>((value & 0x0000ffff) + (value >>16 & 0x0000ffff));
00934     }
00935 };
00936 
00937 template <typename Type, typename TSrc>
00938 struct NumberOfTrailingZeros : public std::unary_function<OpEmulationState*, Type>
00939 {
00940     Type operator()(OpEmulationState* opState)
00941     {
00942         s64 value = static_cast<Type>( TSrc()(opState));
00943         value = (value&(-value))-1;
00944 
00945         value = (value & 0x55555555) + (value >> 1 & 0x55555555);
00946         value = (value & 0x33333333) + (value >> 2 & 0x33333333);
00947         value = (value & 0x0f0f0f0f) + (value >> 4 & 0x0f0f0f0f);
00948         value = (value & 0x00ff00ff) + (value >> 8 & 0x00ff00ff);
00949         return static_cast<Type>((value & 0x0000ffff) + (value >>16 & 0x0000ffff));
00950     }
00951 };
00952 
00953 
00954 // **********************************
00955 //    fp arithmetic operations
00956 // **********************************
00957 
00958 // sign from src1 and the rest from src2
00959 template <typename TSrc1, typename TSrc2>
00960 struct FPDoubleCopySign : public std::unary_function<OpEmulationState*, u64>
00961 {
00962     u64 operator()(OpEmulationState* opState)
00963     {
00964         u64 lhs = static_cast<u64>( TSrc1()(opState) );
00965         u64 rhs = static_cast<u64>( TSrc2()(opState) );
00966 
00967         return (lhs & (u64)0x8000000000000000ULL) | (rhs & ~(u64)0x8000000000000000ULL);
00968     }
00969 };
00970 
00971 template <typename TSrc1, typename TSrc2>
00972 struct FPDoubleCopySignNeg : public std::unary_function<OpEmulationState*, u64>
00973 {
00974     u64 operator()(OpEmulationState* opState)
00975     {
00976         u64 lhs = static_cast<u64>( TSrc1()(opState) );
00977         u64 rhs = static_cast<u64>( TSrc2()(opState) );
00978 
00979         return (~lhs & (u64)0x8000000000000000ULL) | (rhs & ~(u64)0x8000000000000000ULL);
00980     }
00981 };
00982 
00983 // sign & exp from src1 and mantissa from src2
00984 template <typename TSrc1, typename TSrc2>
00985 struct FPDoubleCopySignExp : public std::unary_function<OpEmulationState*, u64>
00986 {
00987     u64 operator()(OpEmulationState* opState)
00988     {
00989         u64 lhs = static_cast<u64>( TSrc1()(opState) );
00990         u64 rhs = static_cast<u64>( TSrc2()(opState) );
00991 
00992         return (lhs & (u64)0xfff0000000000000ULL) | (rhs & ~(u64)0xfff0000000000000ULL);
00993     }
00994 };
00995 
00996 
00997 template <typename Type, typename TSrc1>
00998 struct FPNeg : public std::unary_function<OpEmulationState*, Type>
00999 {
01000     Type operator()(OpEmulationState* opState)
01001     {
01002         return -TSrc1()(opState);
01003     }
01004 };
01005 
01006 template <typename Type, typename TSrc1>
01007 struct FPAbs : public std::unary_function<OpEmulationState*, Type>
01008 {
01009     Type operator()(OpEmulationState* opState)
01010     {
01011         return std::fabs( TSrc1()(opState) );
01012     }
01013 };
01014 
01015 template <typename Type, typename TSrc1, typename TSrc2, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01016 struct FPAdd : public std::unary_function<OpEmulationState*, Type>
01017 {
01018     Type operator()(OpEmulationState* opState)
01019     {
01020         Type lhs = TSrc1()(opState);
01021         Type rhs = TSrc2()(opState);
01022 
01023         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01024         volatile Type rvalue = lhs + rhs;
01025         return rvalue;
01026     }
01027 };
01028 
01029 template <typename Type, typename TSrc1, typename TSrc2, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01030 struct FPSub : public std::unary_function<OpEmulationState*, Type>
01031 {
01032     Type operator()(OpEmulationState* opState)
01033     {
01034         Type lhs = TSrc1()(opState);
01035         Type rhs = TSrc2()(opState);
01036 
01037         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01038         volatile Type rvalue = lhs - rhs;
01039         return rvalue;
01040     }
01041 };
01042 
01043 template <typename Type, typename TSrc1, typename TSrc2, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01044 struct FPMul : public std::unary_function<OpEmulationState*, Type>
01045 {
01046     Type operator()(OpEmulationState* opState)
01047     {
01048         Type lhs = TSrc1()(opState);
01049         Type rhs = TSrc2()(opState);
01050 
01051         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01052         volatile Type rvalue = lhs * rhs;
01053         return rvalue;
01054     }
01055 };
01056 
01057 template <typename Type, typename TSrc1, typename TSrc2, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01058 struct FPDiv : public std::unary_function<OpEmulationState*, Type>
01059 {
01060     Type operator()(OpEmulationState* opState)
01061     {
01062         Type lhs = TSrc1()(opState);
01063         Type rhs = TSrc2()(opState);
01064 
01065         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01066         volatile Type rvalue = lhs / rhs;
01067         return rvalue;
01068     }
01069 };
01070 
01071 template <typename Type, typename TSrc1, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01072 struct FPSqrt : public std::unary_function<OpEmulationState*, Type>
01073 {
01074     Type operator()(OpEmulationState* opState)
01075     {
01076         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01077         volatile Type rvalue = std::sqrt( TSrc1()(opState) );
01078         return rvalue;
01079     }
01080 };
01081 
01082 template <typename Type, typename TSrc1, typename TSrc2, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
01083 struct FPSubTest : public std::unary_function<OpEmulationState*, Type>
01084 {
01085     Type operator()(OpEmulationState* opState)
01086     {
01087         volatile Type lhs = TSrc1()(opState);
01088         volatile Type rhs = TSrc2()(opState);
01089 
01090         Onikiri::ScopedFESetRound sr( RoundMode()(opState) );
01091         volatile Type rvalue = lhs - rhs;
01092         return rvalue;
01093     }
01094 };
01095 
01096 template < int lhs, u64 rhs, int mode, u64 correct >
01097 static bool FpSubTestFunc( OpEmulationState* opState )
01098 {
01099     typedef double                               Dst;
01100     typedef Cast< double, IntConst< int, lhs > > Src1;
01101     typedef AsFP< double, IntConst< u64, rhs > > Src2;
01102     typedef IntConst< int, mode >                Round;
01103 
01104     Dst result = FPSubTest< Dst, Src1, Src2, Round >()( opState );
01105     return AsIntFunc< u64, double >( result ) == correct;
01106 }
01107 
01108 inline void testroundmode(OpEmulationState* opState)
01109 {
01110     bool testResult;
01111 
01112     // IEEE double has a significand with 53 bits of precision.
01113     // So, we test rounding modes with 1 (or -1) subtracted by 1.xx * 2^(-53).
01114     // The results are rounded to [-]1 - (1 * 2^(-53)) or [-]1 - (2 * 2^(-53))
01115     // depending on the rounding modes.
01116 
01117     // Double precision floating-point numbers are displayed in hexadecimal as follows:
01118     // 1.75 * 2^(-53) == 0x3cac000000000000
01119     // 1.25 * 2^(-53) == 0x3ca4000000000000
01120     // 1 - (1 * 2^(-53)) == 0x3fefffffffffffff
01121     // 1 - (2 * 2^(-53)) == 0x3feffffffffffffe
01122     // -1 - (1 * 2^(-53)) == 0xbff0000000000000
01123     // -1 - (2 * 2^(-53)) == 0xbff0000000000001
01124 
01125     testResult = FpSubTestFunc< 1,0x3cac000000000000,FE_DOWNWARD,0x3feffffffffffffe >(opState)
01126         && FpSubTestFunc< 1,0x3cac000000000000,FE_UPWARD,0x3fefffffffffffff >(opState)
01127         && FpSubTestFunc< 1,0x3cac000000000000,FE_TONEAREST,0x3feffffffffffffe >(opState)
01128         && FpSubTestFunc< 1,0x3cac000000000000,FE_TOWARDZERO,0x3feffffffffffffe >(opState)
01129         && FpSubTestFunc< 1,0x3ca4000000000000,FE_DOWNWARD,0x3feffffffffffffe >(opState)
01130         && FpSubTestFunc< 1,0x3ca4000000000000,FE_UPWARD,0x3fefffffffffffff >(opState)
01131         && FpSubTestFunc< 1,0x3ca4000000000000,FE_TONEAREST,0x3fefffffffffffff >(opState)
01132         && FpSubTestFunc< 1,0x3ca4000000000000,FE_TOWARDZERO,0x3feffffffffffffe >(opState)
01133         && FpSubTestFunc< -1,0x3cac000000000000,FE_DOWNWARD,0xbff0000000000001 >(opState)
01134         && FpSubTestFunc< -1,0x3cac000000000000,FE_UPWARD,0xbff0000000000000 >(opState)
01135         && FpSubTestFunc< -1,0x3cac000000000000,FE_TONEAREST,0xbff0000000000001 >(opState)
01136         && FpSubTestFunc< -1,0x3cac000000000000,FE_TOWARDZERO,0xbff0000000000000 >(opState);
01137 
01138     if (!testResult)
01139     {
01140         g_env.Print("\nFP rounding mode test failed. Programs may not be executed precisely.\n");
01141     }
01142 }
01143 
01144 
01145 // **********************************
01146 //    branch operations
01147 // **********************************
01148 
01149 // relative: next_pc + disp*sizeof(Code)
01150 // 
01151 // call saves next_pc to TDest
01152 template <typename TSrcDisp>
01153 inline void BranchRelUncond(OpEmulationState* opState)
01154 {
01155     u64 target = next_pc(opState) + 4*cast_to_signed( TSrcDisp()(opState) );
01156     do_branch(opState, target);
01157 
01158     opState->SetTakenPC(target);
01159 }
01160 
01161 template <typename TSrcTarget>
01162 inline void BranchAbsUncond(OpEmulationState* opState)
01163 {
01164     // <TODO> 0x03
01165     RegisterType addr = TSrcTarget()(opState) & ~(RegisterType)0x03;
01166     do_branch(opState, addr );
01167 
01168     opState->SetTakenPC(addr);
01169 }
01170 
01171 template <typename TSrcDisp, typename TCond>
01172 inline void BranchRelCond(OpEmulationState* opState)
01173 {
01174     if ( TCond()(opState) ) {
01175         BranchRelUncond<TSrcDisp>(opState);
01176     }
01177     else {
01178         opState->SetTakenPC( next_pc(opState) + 4*cast_to_signed( TSrcDisp()(opState) ));
01179     }
01180 }
01181 
01182 template <typename TSrcTarget, typename TCond>
01183 inline void BranchAbsCond(OpEmulationState* opState)
01184 {
01185     if ( TCond()(opState) ) {
01186         BranchAbsUncond<TSrcTarget>(opState);
01187     }
01188     else {
01189         RegisterType addr = TSrcTarget()(opState) & ~(RegisterType)0x03;
01190         opState->SetTakenPC( addr );
01191     }
01192 }
01193 
01194 
01195 template <typename TDest, typename TSrcDisp>
01196 inline void CallRelUncond(OpEmulationState* opState)
01197 {
01198     RegisterType ret_addr = static_cast<RegisterType>( next_pc(opState) );
01199     BranchRelUncond<TSrcDisp>(opState);
01200     TDest::SetOperand(opState, ret_addr );
01201 }
01202 
01203 template <typename TDest, typename TSrcTarget>
01204 inline void CallAbsUncond(OpEmulationState* opState)
01205 {
01206     // <TODO> 0x03
01207     RegisterType ret_addr = static_cast<RegisterType>( next_pc(opState) );
01208     BranchAbsUncond<TSrcTarget>(opState);
01209     TDest::SetOperand(opState, ret_addr );
01210 }
01211 
01212 } // namespace Operation {
01213 } // namespace EmulatorUtility {
01214 } // namespace Onikiri
01215 
01216 #endif // #ifndef EMU_UTILITY_EMULATORUTILITY_GENERIC_OPERATION_H
01217 

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