From 84f0b0a84ca7c161ae9f37ea3eacf69bdd4e9ffc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 30 Mar 2022 16:43:09 -0400 Subject: [PATCH] Test rotates. --- InstructionSets/PowerPC/Instruction.hpp | 14 ++- .../DingusdevPowerPCTests.mm | 103 ++++++++++++++++++ 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/InstructionSets/PowerPC/Instruction.hpp b/InstructionSets/PowerPC/Instruction.hpp index ac7a6a35d..fa724ef21 100644 --- a/InstructionSets/PowerPC/Instruction.hpp +++ b/InstructionSets/PowerPC/Instruction.hpp @@ -425,7 +425,18 @@ enum class Operation: uint8_t { /// rA(), rB(), rD() mullwx, - nandx, negx, norx, orx, orcx, ori, oris, rfi, rlwimix, rlwinmx, rlwnmx, + nandx, negx, norx, orx, orcx, ori, oris, rfi, rlwimix, + + /// Rotate left word immediate then AND with mask. + /// rlwinm rlwinm. + /// rA(), rS(), sh(), mb(), me(), rc() + rlwinmx, + + /// Rotate left word then AND with mask + /// rlwimi rlwimi. + /// rA(), rB(), rS(), mb(), me(), rc() + rlwnmx, + sc, slwx, srawx, srawix, srwx, stb, stbu, /// Store byte with update indexed. @@ -620,7 +631,6 @@ struct Instruction { uint32_t nb() const { return (opcode >> 11) & 0x1f; } /// Specifies a shift amount. - /// TODO: possibly bit 30 is also used in 64-bit mode, find out. uint32_t sh() const { return (opcode >> 11) & 0x1f; } /// Specifies one of the 16 segment registers [32-bit only]. diff --git a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm index a3cad7833..e2476003c 100644 --- a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm +++ b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm @@ -33,6 +33,11 @@ void AssertEqualOperationNameOE(NSString *lhs, Instruction instruction, NSString XCTAssertEqualObjects(lhs, rhs); } +void AssertEqualR(NSString *name, uint32_t reg) { + NSString *const regName = [NSString stringWithFormat:@"r%d", reg]; + XCTAssertEqualObjects(name, regName); +} + NSString *condition(uint32_t code) { NSString *suffix; switch(Condition(code & 3)) { @@ -101,6 +106,104 @@ NSString *condition(uint32_t code) { NSAssert(FALSE, @"Didn't handle %@", line); break; + case Operation::rlwinmx: { + // This maps the opposite way from most of the other tests + // owing to the simplified names being a shade harder to + // detect motivationally. + XCTAssertEqual((instruction.rc() != 0), ([operation characterAtIndex:operation.length - 1] == '.')); + AssertEqualR(columns[3], instruction.rA()); + AssertEqualR(columns[4], instruction.rS()); + + const auto n = [columns[5] intValue]; + const auto b = columns.count > 6 ? [columns[6] intValue] : 0; + + if([operation isEqualToString:@"extlwi"] || [operation isEqualToString:@"extlwi."]) { + XCTAssertEqual(instruction.sh(), b); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), n - 1); + break; + } + + if([operation isEqualToString:@"extrwi"] || [operation isEqualToString:@"extrwi."]) { + XCTAssertEqual(instruction.sh(), b + n); + XCTAssertEqual(instruction.mb(), 32 - n); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"inslwi"] || [operation isEqualToString:@"inslwi."]) { + XCTAssertEqual(instruction.sh(), 32 - b); + XCTAssertEqual(instruction.mb(), b); + XCTAssertEqual(instruction.me(), b + n - 1); + break; + } + + if([operation isEqualToString:@"insrwi"] || [operation isEqualToString:@"insrwi."]) { + XCTAssertEqual(instruction.sh(), 32 - (b + n)); + XCTAssertEqual(instruction.mb(), b); + XCTAssertEqual(instruction.me(), b + n - 1); + break; + } + + if([operation isEqualToString:@"rotlwi"] || [operation isEqualToString:@"rotlwi."]) { + XCTAssertEqual(instruction.sh(), n); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"rotrwi"] || [operation isEqualToString:@"rotrwi."]) { + XCTAssertEqual(instruction.sh(), 32 - n); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"rotlw"] || [operation isEqualToString:@"rotlw."]) { + XCTAssertEqual(instruction.rB(), n); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"slwi"] || [operation isEqualToString:@"slwi."]) { + XCTAssertEqual(instruction.sh(), n); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), 31 - n); + break; + } + + if([operation isEqualToString:@"srwi"] || [operation isEqualToString:@"srwi."]) { + XCTAssertEqual(instruction.sh(), 32 - n); + XCTAssertEqual(instruction.mb(), n); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"clrlwi"] || [operation isEqualToString:@"clrlwi."]) { + XCTAssertEqual(instruction.sh(), 0); + XCTAssertEqual(instruction.mb(), n); + XCTAssertEqual(instruction.me(), 31); + break; + } + + if([operation isEqualToString:@"clrrwi"] || [operation isEqualToString:@"clrrwi."]) { + XCTAssertEqual(instruction.sh(), 0); + XCTAssertEqual(instruction.mb(), 0); + XCTAssertEqual(instruction.me(), 31 - n); + break; + } + + if([operation isEqualToString:@"clrlslwi"] || [operation isEqualToString:@"clrlslwi."]) { + XCTAssertEqual(instruction.sh(), n); + XCTAssertEqual(instruction.mb(), b - n); + XCTAssertEqual(instruction.me(), 31 - n); + break; + } + + NSAssert(FALSE, @"Didn't handle %@", line); + } break; + #define CRMod(x) \ case Operation::x: \ AssertEqualOperationName(operation, @#x); \