diff --git a/InstructionSets/PowerPC/Instruction.hpp b/InstructionSets/PowerPC/Instruction.hpp index a0694d74c..b0b742791 100644 --- a/InstructionSets/PowerPC/Instruction.hpp +++ b/InstructionSets/PowerPC/Instruction.hpp @@ -56,6 +56,14 @@ enum class BranchOption: uint32_t { Always = 0b1010, }; + +/// @returns @c 0 if reg == 0; @c ~0 otherwise. +/// @discussion Provides a branchless way to substitute the value 0 for the value of r0 +/// in affected instructions. +template constexpr IntT is_zero_mask(uint32_t reg) { + return ~IntT((reg - 1) >> 5); +} + enum class Operation: uint8_t { Undefined, @@ -632,7 +640,30 @@ enum class Operation: uint8_t { /// rD() mfcr, - mffsx, mfmsr, mfspr, mfsr, mfsrin, + /// Move from FPSCR. + /// mffs mffs. + /// frD() [rc()] + mffsx, + + /// Move from machine state register. + /// mfmsr + /// rD() + mfmsr, + + /// Move from special purpose record. + /// mfmsr + /// rD(), spr() + mfspr, + + /// Move from segment register. + /// mfsr + /// rD(), sr() + mfsr, + + /// Move from segment register indirect. + /// mfsrin + /// rD(), rB() + mfsrin, /// Move to condition register fields. /// mtcrf @@ -659,7 +690,25 @@ enum class Operation: uint8_t { /// crfD(), imm() mtfsfix, - mtmsr, mtspr, mtsr, mtsrin, + /// Move to FPSCR. + /// mtfs + /// frS() + mtmsr, + + /// Move to special purpose record. + /// mtmsr + /// rD(), spr() + mtspr, + + /// Move to segment register. + /// mfsr + /// sr(), rS() + mtsr, + + /// Move to segment register indirect. + /// mtsrin + /// rD(), rB() + mtsrin, /// Multiply high word. /// mulhw mulgw. @@ -895,7 +944,19 @@ enum class Operation: uint8_t { // // MARK: - Supervisor, optional. // - tlbia, tlbie, tlbsync, + + /// Translation lookaside buffer invalidate all. + /// tlbia + tlbia, + + /// Translation lookaside buffer invalidate entry. + /// tlbie + /// rB() + tlbie, + + /// Translation lookaside buffer synchronise. + /// tlbsync + tlbsync, // // MARK: - Optional. @@ -1155,6 +1216,12 @@ struct Instruction { uint32_t l() const { return opcode & 0x200000; } /// Enables setting of OV and SO in the XER; @c 0 or @c non-0. uint32_t oe() const { return opcode & 0x400; } + + + /// Identifies a special purpose register. + uint32_t spr() const { return (opcode >> 11) & 0x3ff; } + /// Identifies a time base register. + uint32_t tbr() const { return (opcode >> 11) & 0x3ff; } }; // Sanity check on Instruction size. diff --git a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm index f1450ad0c..1452b3dee 100644 --- a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm +++ b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm @@ -315,6 +315,33 @@ NSString *offset(Instruction instruction) { XCTAssertEqualObjects(columns[3], conditionreg(instruction.crfD())); break; + case Operation::mffsx: + AssertEqualOperationNameE(operation, @"mffsx", instruction); + AssertEqualFR(columns[3], instruction.frD()); + break; + + case Operation::mtmsr: + AssertEqualOperationName(operation, @"mtmsr"); + AssertEqualR(columns[3], instruction.rS()); + break; + + case Operation::mtsrin: + AssertEqualOperationName(operation, @"mtsrin"); + AssertEqualR(columns[3], instruction.rD()); + AssertEqualR(columns[4], instruction.rB()); + break; + + case Operation::mtsr: + AssertEqualOperationName(operation, @"mtsr"); + XCTAssertEqual([columns[3] intValue], instruction.sr()); + AssertEqualR(columns[4], instruction.rS()); + break; + + case Operation::tlbie: + AssertEqualOperationName(operation, @"tlbie"); + AssertEqualR(columns[3], instruction.rB()); + break; + case Operation::icbi: AssertEqualOperationName(operation, @"icbi"); AssertEqualR(columns[3], instruction.rA(), false); @@ -398,12 +425,24 @@ NSString *offset(Instruction instruction) { AssertEqualOperationName(operation, @#x); \ break; - NoArg(isync); - NoArg(sync); - NoArg(eieio); + NoArg(isync); + NoArg(sync); + NoArg(eieio); + NoArg(tlbia); #undef NoArg +#define D(x) \ + case Operation::x: \ + AssertEqualOperationName(operation, @#x); \ + AssertEqualR(columns[3], instruction.rD()); \ + break; + + D(mfcr); + D(mfmsr); + +#undef D + #define Shift(x) \ case Operation::x: \ AssertEqualOperationNameE(operation, @#x, instruction); \ @@ -412,9 +451,9 @@ NSString *offset(Instruction instruction) { AssertEqualR(columns[5], instruction.rB()); \ break; - Shift(slwx); - Shift(srwx); - Shift(srawx); + Shift(slwx); + Shift(srwx); + Shift(srawx); #undef Shift @@ -500,21 +539,13 @@ NSString *offset(Instruction instruction) { ABCz(lwzux); ABCz(lbzx); ABCz(lbzux); - ABCz(stwx); - ABCz(stwux); - ABCz(stbx); - ABCz(stbux); ABCz(lhzx); ABCz(lhzux); ABCz(lhax); ABCz(lhaux); - ABCz(sthx); - ABCz(sthux); ABCz(lhbrx); ABCz(lwbrx); ABCz(lwarx); - ABCz(stwbrx); - ABCz(sthbrx); ABCz(eciwx); ABCz(lswx); ABCz(lwa); @@ -582,7 +613,20 @@ NSString *offset(Instruction instruction) { AssertEqualR(columns[5], instruction.rB()); \ break; + SAB(ecowx); + SAB(stbux); + SAB(stbx); + SAB(sthbrx); + SAB(sthux); + SAB(sthx); + SAB(stswx); + SAB(stwbrx); SAB(stwcx_); + SAB(stwux); + SAB(stwx); + SAB(stdcx_); + SAB(stdux); + SAB(stdx); #undef SAB