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 PPC64_LINUX_PPC64LINUX_PPC64OPERATION_H
00033 #define PPC64_LINUX_PPC64LINUX_PPC64OPERATION_H
00034
00035 #include "SysDeps/fenv.h"
00036 #include "Lib/shttl/bit.h"
00037 #include "Emu/Utility/GenericOperation.h"
00038 #include "Emu/Utility/System/Syscall/SyscallConvIF.h"
00039 #include "Emu/Utility/System/ProcessState.h"
00040
00041 namespace Onikiri {
00042 namespace PPC64Linux {
00043 namespace Operation {
00044
00045 using namespace EmulatorUtility;
00046 using namespace EmulatorUtility::Operation;
00047
00048
00049
00050
00051
00052
00053 template <typename Type>
00054 inline int PPC64CalcFlag(Type lhs, Type rhs = 0)
00055 {
00056 if (lhs == rhs) {
00057 return 0x2;
00058 }
00059 else if (lhs > rhs) {
00060 return 0x4;
00061 }
00062 else if (lhs < rhs) {
00063 return 0x8;
00064 }
00065
00066 return 0;
00067 }
00068
00069
00070 template <typename Type>
00071 inline int PPC64CalcFlagFP(Type lhs, Type rhs = 0)
00072 {
00073 if (IsNAN(lhs) || IsNAN(rhs)) {
00074 return 0x1;
00075 }
00076 else if (lhs == rhs) {
00077 return 0x2;
00078 }
00079 else if (lhs > rhs) {
00080 return 0x4;
00081 }
00082 else if (lhs < rhs) {
00083 return 0x8;
00084 }
00085
00086 return 0;
00087 }
00088
00089
00090 template <typename Type>
00091 inline Type PPC64GenMask(unsigned int mb, unsigned int me)
00092 {
00093 unsigned int typeBits = sizeof(Type)*8;
00094
00095 if (mb > me) {
00096
00097 return ~(Type)(shttl::mask(0, mb-me-1) << (typeBits-mb));
00098 }
00099 else {
00100
00101 return (Type)(shttl::mask(0, me-mb+1) << (typeBits-me-1));
00102 }
00103 }
00104
00105
00106 inline u64 PPC64AdjustFPSCR(u64 fpscr)
00107 {
00108 fpscr &= 0x9fffffff;
00109
00110 if (fpscr & 0x00000f80)
00111 fpscr |= 0x40000000;
00112 if (fpscr & 0x01807000)
00113 fpscr |= 0x20000000;
00114
00115 return fpscr;
00116 }
00117
00118
00119 template <typename TFPSCR>
00120 struct PPC64FPSCRRoundMode : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00121 {
00122 int operator()(EmulatorUtility::OpEmulationState* opState)
00123 {
00124 switch (TFPSCR()(opState) & 0x3) {
00125 case 0:
00126 return FE_TONEAREST;
00127 case 1:
00128 return FE_TOWARDZERO;
00129 case 2:
00130 return FE_UPWARD;
00131 case 3:
00132 return FE_DOWNWARD;
00133 default:
00134 ASSERT(0);
00135 return FE_ROUNDDEFAULT;
00136 }
00137 }
00138 };
00139
00140
00141
00142
00143 template <typename TSrcCR, typename TSrcBit>
00144 struct PPC64CRBit : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00145 {
00146 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00147 {
00148 ASSERT(TSrcBit()(opState) < 4);
00149 return (TSrcCR()(opState) >> (3-TSrcBit()(opState))) & 0x1;
00150 }
00151 };
00152
00153
00154 template <typename TDestCTR, typename TSrcCTR>
00155 struct PPC64DecCTR : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00156 {
00157 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00158 {
00159 u64 result = TSrcCTR()(opState) - 1;
00160 TDestCTR::SetOperand(opState, result);
00161 return result;
00162 }
00163 };
00164
00165
00166
00167
00168 inline void PPC64SyscallSetArg(EmulatorUtility::OpEmulationState* opState)
00169 {
00170 EmulatorUtility::SyscallConvIF* syscallConv = opState->GetProcessState()->GetSyscallConv();
00171 syscallConv->SetArg(0, SrcOperand<0>()(opState));
00172 syscallConv->SetArg(1, SrcOperand<1>()(opState));
00173 syscallConv->SetArg(2, SrcOperand<2>()(opState));
00174 }
00175
00176
00177 inline void PPC64SyscallCore(EmulatorUtility::OpEmulationState* opState)
00178 {
00179 EmulatorUtility::SyscallConvIF* syscallConv = opState->GetProcessState()->GetSyscallConv();
00180 syscallConv->SetArg(3, SrcOperand<0>()(opState));
00181 syscallConv->SetArg(4, SrcOperand<1>()(opState));
00182 syscallConv->SetArg(5, SrcOperand<2>()(opState));
00183 syscallConv->SetArg(6, SrcOperand<3>()(opState));
00184 syscallConv->Execute(opState);
00185
00186 DstOperand<0>::SetOperand(opState, syscallConv->GetResult(EmulatorUtility::SyscallConvIF::RetValueIndex) );
00187 if (syscallConv->GetResult(EmulatorUtility::SyscallConvIF::ErrorFlagIndex))
00188 DstOperand<1>::SetOperand(opState, 1);
00189 else
00190 DstOperand<1>::SetOperand(opState, 0);
00191 }
00192
00193
00194
00195
00196
00197
00198 template <typename Type, typename TSrc>
00199 struct PPC64Cntlz : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00200 {
00201 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00202 {
00203 int lz = sizeof(Type)*8;
00204 Type value = static_cast<Type>( TSrc()(opState) );
00205
00206
00207 while (value != 0) {
00208 lz --;
00209 value >>= 1;
00210 }
00211
00212 return lz;
00213 }
00214 };
00215
00216
00217 template <typename Type, typename TSrc, typename TMaskBegin, typename TMaskEnd>
00218 struct PPC64Mask : public std::unary_function<EmulatorUtility::OpEmulationState*, Type>
00219 {
00220 Type operator()(EmulatorUtility::OpEmulationState* opState)
00221 {
00222 unsigned int typeBits = sizeof(Type)*8;
00223 unsigned int mb = static_cast<int>( TMaskBegin()(opState) & (typeBits-1) );
00224 unsigned int me = static_cast<int>( TMaskEnd()(opState) & (typeBits-1) );
00225
00226 return static_cast<Type>(TSrc()(opState)) & PPC64GenMask<Type>(mb, me);
00227 }
00228 };
00229
00230
00231 template <typename Type, typename TSrc1, typename TSrc2, typename TMaskBegin, typename TMaskEnd>
00232 struct PPC64MaskInsert : public std::unary_function<EmulatorUtility::OpEmulationState*, Type>
00233 {
00234 Type operator()(EmulatorUtility::OpEmulationState* opState)
00235 {
00236 unsigned int typeBits = sizeof(Type)*8;
00237 unsigned int mb = static_cast<int>( TMaskBegin()(opState) & (typeBits-1) );
00238 unsigned int me = static_cast<int>( TMaskEnd()(opState) & (typeBits-1) );
00239 Type mask = PPC64GenMask<Type>(mb, me);
00240
00241 return (static_cast<Type>(TSrc2()(opState)) & mask) | (static_cast<Type>(TSrc1()(opState)) & ~mask);
00242 }
00243 };
00244
00245
00246
00247
00248
00249
00250
00251 template <typename Type, typename TSrc1, typename TSrc2>
00252 struct PPC64Compare : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00253 {
00254 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00255 {
00256 return PPC64CalcFlag(static_cast<Type>(TSrc1()(opState)), static_cast<Type>(TSrc2()(opState)));
00257 }
00258 };
00259
00260 template <typename Type, typename TSrc1, typename TSrc2>
00261 struct PPC64FPCompare : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00262 {
00263 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00264 {
00265 return PPC64CalcFlagFP(static_cast<Type>(TSrc1()(opState)), static_cast<Type>(TSrc2()(opState)));
00266 }
00267 };
00268
00269
00270
00271
00272
00273
00274
00275
00276 template <typename Type, typename TSrc, typename RoundMode = IntConst<int, FE_ROUNDDEFAULT> >
00277 struct PPC64FPToInt : public std::unary_function<EmulatorUtility::OpEmulationState*, Type>
00278 {
00279 Type operator()(EmulatorUtility::OpEmulationState* opState)
00280 {
00281 typedef typename EmulatorUtility::signed_type<Type>::type SignedType;
00282 typedef typename TSrc::result_type FPType;
00283
00284 const SignedType maxValue = std::numeric_limits<SignedType>::max();
00285 const SignedType minValue = std::numeric_limits<SignedType>::min();
00286 FPType value = static_cast<FPType>( TSrc()(opState) );
00287
00288 if (value > static_cast<FPType>(maxValue))
00289 return maxValue;
00290 else if (value < static_cast<FPType>(minValue))
00291 return minValue;
00292 else
00293 return static_cast<Type>(value);
00294 }
00295 };
00296
00297
00298 template <typename TSrc>
00299 struct PPC64FRIN : public std::unary_function<EmulatorUtility::OpEmulationState*, double>
00300 {
00301 double operator()(EmulatorUtility::OpEmulationState* opState)
00302 {
00303 double value = static_cast<double>( TSrc()(opState) );
00304
00305 if (value > 0.0)
00306 return floor(value+0.5);
00307 else
00308 return ceil(value-0.5);
00309 }
00310 };
00311
00312
00313 template <typename TSrc>
00314 struct PPC64FRIZ : public std::unary_function<EmulatorUtility::OpEmulationState*, double>
00315 {
00316 double operator()(EmulatorUtility::OpEmulationState* opState)
00317 {
00318 double value = static_cast<double>( TSrc()(opState) );
00319
00320 if (value > 0.0)
00321 return floor(value);
00322 else
00323 return ceil(value);
00324 }
00325 };
00326
00327
00328 template <typename TSrc>
00329 struct PPC64FRIP : public std::unary_function<EmulatorUtility::OpEmulationState*, double>
00330 {
00331 double operator()(EmulatorUtility::OpEmulationState* opState)
00332 {
00333 double value = static_cast<double>( TSrc()(opState) );
00334 return ceil(value);
00335 }
00336 };
00337
00338
00339 template <typename TSrc>
00340 struct PPC64FRIM : public std::unary_function<EmulatorUtility::OpEmulationState*, double>
00341 {
00342 double operator()(EmulatorUtility::OpEmulationState* opState)
00343 {
00344 double value = static_cast<double>( TSrc()(opState) );
00345 return floor(value);
00346 }
00347 };
00348
00349
00350
00351
00352
00353
00354
00355 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00356 struct PPC64CRAnd : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00357 {
00358 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00359 {
00360 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) & shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState)));
00361 }
00362 };
00363 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00364 struct PPC64CRNand : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00365 {
00366 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00367 {
00368 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) & shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState))) ^ 1;
00369 }
00370 };
00371 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00372 struct PPC64CROr : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00373 {
00374 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00375 {
00376 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) | shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState)));
00377 }
00378 };
00379 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00380 struct PPC64CRNor : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00381 {
00382 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00383 {
00384 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) | shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState))) ^ 1;
00385 }
00386 };
00387 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00388 struct PPC64CRXor : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00389 {
00390 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00391 {
00392 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) ^ shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState)));
00393 }
00394 };
00395 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00396 struct PPC64CREqv : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00397 {
00398 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00399 {
00400 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) ^ shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState))) ^ 1;
00401 }
00402 };
00403 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00404 struct PPC64CRAndC : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00405 {
00406 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00407 {
00408 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) | !shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState)));
00409 }
00410 };
00411 template <typename TSrcCR1, typename TSrcCI1, typename TSrcCR2, typename TSrcCI2>
00412 struct PPC64CROrC : public std::unary_function<EmulatorUtility::OpEmulationState*, u64>
00413 {
00414 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00415 {
00416 return (shttl::test(TSrcCR1()(opState), 3-TSrcCI1()(opState)) | !shttl::test(TSrcCR2()(opState), 3-TSrcCI2()(opState)));
00417 }
00418 };
00419
00420
00421
00422
00423
00424
00425 template <typename Type, typename TSrc1, typename TSrc2, unsigned int count_mask>
00426 struct PPC64CarryOfAShiftR : public std::unary_function<EmulatorUtility::OpEmulationState*, Type>
00427 {
00428 Type operator()(EmulatorUtility::OpEmulationState* opState)
00429 {
00430 Type value = static_cast<Type>( TSrc1()(opState) );
00431 size_t count = static_cast<size_t>( TSrc2()(opState) ) & count_mask;
00432
00433 if ((value & ((Type)1 << (sizeof(Type)*8-1)))
00434 && (value & shttl::mask(0, std::min(count, sizeof(Type)*8)))
00435 )
00436 return 1;
00437 else
00438 return 0;
00439 }
00440 };
00441
00442
00443
00444
00445
00446 template <typename Type, typename TAddrDest, typename TAddr>
00447 struct PPC64LoadWithUpdate : public std::unary_function<EmulatorUtility::OpEmulationState*, Type>
00448 {
00449 Type operator()(EmulatorUtility::OpEmulationState* opState)
00450 {
00451 u64 addr = TAddr()(opState);
00452 Type value = ReadMemory<Type>( opState, addr );
00453
00454 TAddrDest::SetOperand( opState, addr );
00455 return value;
00456 }
00457 };
00458
00459 template <typename Type, typename TAddrDest, typename TValue, typename TAddr>
00460 inline void PPC64StoreWithUpdate(EmulatorUtility::OpEmulationState* opState)
00461 {
00462 u64 addr = TAddr()(opState);
00463 WriteMemory<Type>(opState, addr, static_cast<Type>( TValue()(opState) ));
00464 TAddrDest::SetOperand( opState, addr );
00465 }
00466
00467
00468
00469
00470 template <typename TSrcFlag, typename TSrcField, typename TSrcValue>
00471 struct PPC64MTFSFI : public std::unary_function<EmulatorUtility::OpEmulationState*, u64 >
00472 {
00473 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00474 {
00475 u64 fpscr = TSrcFlag()(opState);
00476 u64 value = TSrcValue()(opState) & shttl::mask(0, 4);
00477 int field = static_cast<int>(TSrcField()(opState));
00478 int bit_pos = 4*(7-field);
00479 u64 mask = ~shttl::mask(bit_pos, 4);
00480
00481 return (fpscr & mask) | (value << bit_pos);
00482 }
00483 };
00484
00485 template <typename TSrcFlag, typename TSrcFieldMask, typename TSrcValue>
00486 struct PPC64MTFSF : public std::unary_function<EmulatorUtility::OpEmulationState*, u64 >
00487 {
00488 u64 operator()(EmulatorUtility::OpEmulationState* opState)
00489 {
00490 u64 fpscr = TSrcFlag()(opState);
00491 u64 value = TSrcValue()(opState) & shttl::mask(0, 32);
00492 int fieldMask = static_cast<int>(TSrcFieldMask()(opState));
00493
00494 u64 mask = 0;
00495 for (int i = 0; i < 8; i ++) {
00496 if (fieldMask & shttl::mask(i, 1)) {
00497 mask |= shttl::mask(i*4, 4);
00498 }
00499 }
00500 mask = ~mask;
00501
00502 return (fpscr & mask) | value;
00503 }
00504 };
00505
00506
00507
00508
00509
00510
00511
00512 template <typename TDestCR, typename TDestCRI, typename TOrgCR, typename TFunc>
00513 inline void PPC64SetCRBit(EmulatorUtility::OpEmulationState* opState)
00514 {
00515 u64 value = TOrgCR()(opState);
00516
00517 if (TFunc()(opState)) {
00518 value = shttl::set_bit(value, 3-TDestCRI()(opState));
00519 }
00520 else {
00521 value = shttl::reset_bit(value, 3-TDestCRI()(opState));
00522 }
00523
00524 TDestCR::SetOperand(opState, value);
00525 }
00526
00527 template <typename TDest, typename TFunc>
00528 inline void PPC64SetFPSCR(EmulatorUtility::OpEmulationState* opState)
00529 {
00530 typename TFunc::result_type result = PPC64AdjustFPSCR(TFunc()(opState));
00531
00532 TDest::SetOperand(opState, result);
00533 }
00534
00535 template <typename TDest, typename TDestFlag, typename TFunc>
00536 inline void PPC64SetFPSCRF(EmulatorUtility::OpEmulationState* opState)
00537 {
00538 typename TFunc::result_type result = PPC64AdjustFPSCR(TFunc()(opState));
00539
00540 TDest::SetOperand(opState, result);
00541 TDestFlag::SetOperand(opState, result >> 27 & 0xf );
00542 }
00543
00544
00545 template <typename TDest, typename TDestFlag, typename TFunc>
00546 inline void PPC64SetF(EmulatorUtility::OpEmulationState* opState)
00547 {
00548 typename TFunc::result_type result = TFunc()(opState);
00549
00550 TDest::SetOperand(opState, result);
00551 TDestFlag::SetOperand(opState, PPC64CalcFlag(EmulatorUtility::cast_to_signed(result)) );
00552 }
00553
00554
00555 template <typename TDest, typename TDestFlag, typename TFPSCR, typename TFunc>
00556 inline void PPC64SetFPF(EmulatorUtility::OpEmulationState* opState)
00557 {
00558 typename TFunc::result_type result = TFunc()(opState);
00559
00560 TDest::SetOperand(opState, AsIntFunc<RegisterType>( result ));
00561 TDestFlag::SetOperand(opState, TFPSCR()(opState) >> 28 & 0xf );
00562 }
00563
00564
00565 template <typename TDest, typename TDestFlag, typename TFunc>
00566 inline void PPC64SetSextF(EmulatorUtility::OpEmulationState* opState)
00567 {
00568 typename EmulatorUtility::signed_type<typename TFunc::result_type>::type result = EmulatorUtility::cast_to_signed( TFunc()(opState) );
00569
00570 TDest::SetOperand(opState, result);
00571 TDestFlag::SetOperand(opState, PPC64CalcFlag(EmulatorUtility::cast_to_signed(result)) );
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 template <typename TSrcDisp>
00583 inline void PPC64BranchRelUncond(EmulatorUtility::OpEmulationState* opState)
00584 {
00585 u64 target = current_pc(opState) + 4*EmulatorUtility::cast_to_signed( TSrcDisp()(opState) );
00586 do_branch(opState, target);
00587
00588 opState->SetTakenPC(target);
00589 }
00590
00591 template <typename TSrcTarget>
00592 inline void PPC64BranchAbsUncond(EmulatorUtility::OpEmulationState* opState)
00593 {
00594
00595 RegisterType addr = TSrcTarget()(opState) & ~(RegisterType)0x03;
00596 do_branch(opState, addr );
00597
00598 opState->SetTakenPC(addr);
00599 }
00600
00601 template <typename TSrcDisp, typename TCond>
00602 inline void PPC64BranchRelCond(EmulatorUtility::OpEmulationState* opState)
00603 {
00604 if ( TCond()(opState) ) {
00605 PPC64BranchRelUncond<TSrcDisp>(opState);
00606 }
00607 else {
00608 opState->SetTakenPC( current_pc(opState) + 4*EmulatorUtility::cast_to_signed( TSrcDisp()(opState) ));
00609 }
00610 }
00611
00612 template <typename TSrcTarget, typename TCond>
00613 inline void PPC64BranchAbsCond(EmulatorUtility::OpEmulationState* opState)
00614 {
00615 if ( TCond()(opState) ) {
00616 PPC64BranchAbsUncond<TSrcTarget>(opState);
00617 }
00618 else {
00619 RegisterType addr = TSrcTarget()(opState) & ~(RegisterType)0x03;
00620 opState->SetTakenPC( addr );
00621 }
00622 }
00623
00624
00625 template <typename TDest, typename TSrcDisp>
00626 inline void PPC64CallRelUncond(EmulatorUtility::OpEmulationState* opState)
00627 {
00628 RegisterType ret_addr = static_cast<RegisterType>( next_pc(opState) );
00629 PPC64BranchRelUncond<TSrcDisp>(opState);
00630 TDest::SetOperand(opState, ret_addr );
00631 }
00632
00633 template <typename TDest, typename TSrcTarget>
00634 inline void PPC64CallAbsUncond(EmulatorUtility::OpEmulationState* opState)
00635 {
00636
00637 RegisterType ret_addr = static_cast<RegisterType>( next_pc(opState) );
00638 PPC64BranchAbsUncond<TSrcTarget>(opState);
00639 TDest::SetOperand(opState, ret_addr );
00640 }
00641
00642 }
00643 }
00644 }
00645
00646 #endif
00647