@@ -419,6 +419,13 @@ bool Recompiler::Recompile(
419419 println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
420420 break ;
421421
422+ case PPC_INST_ADDC:
423+ println (" \t {}.ca = {}.u32 >= ~{}.u32;" , xer (), r (insn.operands [2 ]), r (insn.operands [1 ]));
424+ println (" \t {}.u64 = {}.u64 + {}.u64;" , r (insn.operands [0 ]), r (insn.operands [1 ]), r (insn.operands [2 ]));
425+ if (strchr (insn.opcode ->name , ' .' ))
426+ println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
427+ break ;
428+
422429 case PPC_INST_ADDE:
423430 println (" \t {}.u8 = ({}.u32 + {}.u32 < {}.u32) | ({}.u32 + {}.u32 + {}.ca < {}.ca);" , temp (), r (insn.operands [1 ]), r (insn.operands [2 ]), r (insn.operands [1 ]), r (insn.operands [1 ]), r (insn.operands [2 ]), xer (), xer ());
424431 println (" \t {}.u64 = {}.u64 + {}.u64 + {}.ca;" , r (insn.operands [0 ]), r (insn.operands [1 ]), r (insn.operands [2 ]), xer ());
@@ -427,6 +434,14 @@ bool Recompiler::Recompile(
427434 println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
428435 break ;
429436
437+ case PPC_INST_ADDME:
438+ println (" \t {}.u8 = ({}.u32 - 1 < {}.u32) | ({}.u32 - 1 + {}.ca < {}.ca);" , temp (), r (insn.operands [1 ]), r (insn.operands [1 ]), r (insn.operands [1 ]), xer (), xer ());
439+ println (" \t {}.u64 = {}.u64 - 1 + {}.ca;" , r (insn.operands [0 ]), r (insn.operands [1 ]), xer ());
440+ println (" \t {}.ca = {}.u8;" , xer (), temp ());
441+ if (strchr (insn.opcode ->name , ' .' ))
442+ println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
443+ break ;
444+
430445 case PPC_INST_ADDI:
431446 print (" \t {}.s64 = " , r (insn.operands [0 ]));
432447 if (insn.operands [1 ] != 0 )
@@ -540,6 +555,14 @@ bool Recompiler::Recompile(
540555 println (" \t if ({}.u32 == 0) goto loc_{:X};" , ctr (), insn.operands [0 ]);
541556 break ;
542557
558+ case PPC_INST_BDZF:
559+ {
560+ constexpr std::string_view fields[] = { " lt" , " gt" , " eq" , " so" };
561+ println (" \t --{}.u64;" , ctr ());
562+ println (" \t if ({}.u32 == 0 && !{}.{}) goto loc_{:X};" , ctr (), cr (insn.operands [0 ] / 4 ), fields[insn.operands [0 ] % 4 ], insn.operands [1 ]);
563+ break ;
564+ }
565+
543566 case PPC_INST_BDZLR:
544567 println (" \t --{}.u64;" , ctr ());
545568 println (" \t if ({}.u32 == 0) return;" , ctr (), insn.operands [0 ]);
@@ -551,10 +574,20 @@ bool Recompiler::Recompile(
551574 break ;
552575
553576 case PPC_INST_BDNZF:
554- // NOTE: assuming eq here as a shortcut because all the instructions in the game do that
577+ {
578+ constexpr std::string_view fields[] = { " lt" , " gt" , " eq" , " so" };
579+ println (" \t --{}.u64;" , ctr ());
580+ println (" \t if ({}.u32 != 0 && !{}.{}) goto loc_{:X};" , ctr (), cr (insn.operands [0 ] / 4 ), fields[insn.operands [0 ] % 4 ], insn.operands [1 ]);
581+ break ;
582+ }
583+
584+ case PPC_INST_BDNZT:
585+ {
586+ constexpr std::string_view fields[] = { " lt" , " gt" , " eq" , " so" };
555587 println (" \t --{}.u64;" , ctr ());
556- println (" \t if ({}.u32 != 0 && ! {}.eq ) goto loc_{:X};" , ctr (), cr (insn.operands [0 ] / 4 ), insn.operands [1 ]);
588+ println (" \t if ({}.u32 != 0 && {}.{} ) goto loc_{:X};" , ctr (), cr (insn.operands [0 ] / 4 ), fields[insn. operands [ 0 ] % 4 ] , insn.operands [1 ]);
557589 break ;
590+ }
558591
559592 case PPC_INST_BEQ:
560593 printConditionalBranch (false , " eq" );
@@ -684,6 +717,20 @@ bool Recompiler::Recompile(
684717 println (" \t {}.u64 = __lzcnt({}.u32);" , r (insn.operands [0 ]), r (insn.operands [1 ]));
685718 break ;
686719
720+ case PPC_INST_CROR:
721+ {
722+ constexpr std::string_view fields[] = { " lt" , " gt" , " eq" , " so" };
723+ println (" \t {}.{} = {}.{} | {}.{};" , cr (insn.operands [0 ] / 4 ), fields[insn.operands [0 ] % 4 ], cr (insn.operands [1 ] / 4 ), fields[insn.operands [1 ] % 4 ], cr (insn.operands [2 ] / 4 ), fields[insn.operands [2 ] % 4 ]);
724+ break ;
725+ }
726+
727+ case PPC_INST_CRORC:
728+ {
729+ constexpr std::string_view fields[] = { " lt" , " gt" , " eq" , " so" };
730+ println (" \t {}.{} = {}.{} | (~{}.{} & 1);" , cr (insn.operands [0 ] / 4 ), fields[insn.operands [0 ] % 4 ], cr (insn.operands [1 ] / 4 ), fields[insn.operands [1 ] % 4 ], cr (insn.operands [2 ] / 4 ), fields[insn.operands [2 ] % 4 ]);
731+ break ;
732+ }
733+
687734 case PPC_INST_DB16CYC:
688735 // no op
689736 break ;
@@ -744,6 +791,13 @@ bool Recompiler::Recompile(
744791 // no op
745792 break ;
746793
794+ case PPC_INST_EQV:
795+ println (" \t {}.u64 = ~({}.u32 ^ {}.u32);" , r (insn.operands [0 ]), r (insn.operands [1 ]), r (insn.operands [2 ]));
796+ if (strchr (insn.opcode ->name , ' .' ))
797+ println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
798+
799+ break ;
800+
747801 case PPC_INST_EXTSB:
748802 println (" \t {}.s64 = {}.s8;" , r (insn.operands [0 ]), r (insn.operands [1 ]));
749803 if (strchr (insn.opcode ->name , ' .' ))
@@ -1711,6 +1765,14 @@ bool Recompiler::Recompile(
17111765 println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
17121766 break ;
17131767
1768+ case PPC_INST_SUBFZE:
1769+ println (" \t {}.u8 = (~{}.u32 < ~{}.u32) | (~{}.u32 + {}.ca < {}.ca);" , temp (), r (insn.operands [1 ]), r (insn.operands [1 ]), r (insn.operands [1 ]), xer (), xer ());
1770+ println (" \t {}.u64 = ~{}.u64 + {}.ca;" , r (insn.operands [0 ]), r (insn.operands [1 ]), xer ());
1771+ println (" \t {}.ca = {}.u8;" , xer (), temp ());
1772+ if (strchr (insn.opcode ->name , ' .' ))
1773+ println (" \t {}.compare<int32_t>({}.s32, 0, {});" , cr (0 ), r (insn.operands [0 ]), xer ());
1774+ break ;
1775+
17141776 case PPC_INST_SUBFIC:
17151777 println (" \t {}.ca = {}.u32 <= {};" , xer (), r (insn.operands [1 ]), insn.operands [2 ]);
17161778 println (" \t {}.s64 = {} - {}.s64;" , r (insn.operands [0 ]), int32_t (insn.operands [2 ]), r (insn.operands [1 ]));
0 commit comments