From 1f44ad17239dc21977ef8ddfc157643a9b2ae222 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 6 Apr 2022 21:09:58 -0400 Subject: [PATCH] Completes test cases. --- InstructionSets/PowerPC/Decoder.cpp | 199 +++++++++++++++++- InstructionSets/PowerPC/Instruction.hpp | 2 +- .../DingusdevPowerPCTests.mm | 63 +++++- 3 files changed, 252 insertions(+), 12 deletions(-) diff --git a/InstructionSets/PowerPC/Decoder.cpp b/InstructionSets/PowerPC/Decoder.cpp index 106c4fdac..a4de269f0 100644 --- a/InstructionSets/PowerPC/Decoder.cpp +++ b/InstructionSets/PowerPC/Decoder.cpp @@ -20,6 +20,203 @@ template Instruc // Otherwise, validation depends on operation // (and, in principle, processor model). + switch(operation) { + case Operation::addmex: case Operation::addzex: + case Operation::bcctrx: case Operation::bclrx: + case Operation::cntlzdx: case Operation::cntlzwx: + case Operation::extsbx: case Operation::extshx: case Operation::extswx: + case Operation::fmulx: case Operation::fmulsx: + case Operation::negx: + case Operation::subfmex: case Operation::subfzex: + if(opcode & 0b000000'00000'00000'11111'0000000000'0) return Instruction(opcode); + break; + + case Operation::cmp: case Operation::cmpl: + if(opcode & 0b000000'00010'00000'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::cmpi: case Operation::cmpli: + if(opcode & 0b000000'00010'00000'00000'0000000000'0) return Instruction(opcode); + break; + + case Operation::dcbf: case Operation::dcbi: case Operation::dcbst: + case Operation::dcbt: case Operation::dcbtst: case Operation::dcbz: + if(opcode & 0b000000'11111'00000'00000'0000000000'0) return Instruction(opcode); + break; + + case Operation::crand: case Operation::crandc: case Operation::creqv: + case Operation::crnand: case Operation::crnor: case Operation::cror: + case Operation::crorc: case Operation::crxor: + case Operation::eciwx: case Operation::ecowx: + case Operation::lbzux: case Operation::lbzx: + case Operation::ldarx: + case Operation::ldux: case Operation::ldx: + case Operation::lfdux: case Operation::lfdx: + case Operation::lfsux: case Operation::lfsx: + case Operation::lhaux: case Operation::lhax: case Operation::lhbrx: + case Operation::lhzux: case Operation::lhzx: + case Operation::lswi: case Operation::lswx: + case Operation::lwarx: case Operation::lwaux: case Operation::lwax: case Operation::lwbrx: + case Operation::lwzux: case Operation::lwzx: + case Operation::mfspr: case Operation::mftb: + case Operation::mtspr: + case Operation::stbux: case Operation::stbx: + case Operation::stdux: case Operation::stdx: + case Operation::stfdux: case Operation::stfdx: + case Operation::stfiwx: + case Operation::stfsux: case Operation::stfsx: + case Operation::sthbrx: + case Operation::sthux: case Operation::sthx: + case Operation::stswi: case Operation::stswx: + case Operation::stwbrx: + case Operation::stwux: case Operation::stwx: + case Operation::td: case Operation::tw: + if(opcode & 0b000000'00000'00000'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::fabsx: case Operation::fcfidx: + case Operation::fctidx: case Operation::fctidzx: + case Operation::fctiwx: case Operation::fctiwzx: + case Operation::fmrx: case Operation::fnabsx: + case Operation::fnegx: case Operation::frspx: + if(opcode & 0b000000'00000'11111'00000'0000000000'0) return Instruction(opcode); + break; + + case Operation::faddx: case Operation::faddsx: + case Operation::fdivx: case Operation::fdivsx: + case Operation::fsubx: case Operation::fsubsx: + if(opcode & 0b000000'00000'00000'00000'1111100000'0) return Instruction(opcode); + break; + + case Operation::fcmpo: case Operation::fcmpu: + if(opcode & 0b000000'00011'00000'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::fresx: case Operation::frsqrtex: + case Operation::fsqrtx: case Operation::fsqrtsx: + if(opcode & 0b000000'00000'11111'00000'1111100000'1) return Instruction(opcode); + break; + + case Operation::icbi: + if(opcode & 0b000000'11111'00000'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::eieio: + case Operation::isync: + case Operation::rfi: + case Operation::slbia: + case Operation::sync: + case Operation::tlbia: + case Operation::tlbsync: + if(opcode & 0b000000'11111'11111'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::mcrf: case Operation::mcrfs: + if(opcode & 0b000000'00011'00011'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::mcrxr: + if(opcode & 0b000000'00011'11111'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::mfcr: + case Operation::mfmsr: + case Operation::mtmsr: + if(opcode & 0b000000'00000'11111'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::mffsx: + case Operation::mtfsb0x: + case Operation::mtfsb1x: + if(opcode & 0b000000'00000'11111'11111'0000000000'0) return Instruction(opcode); + break; + + case Operation::mtfsfx: + if(opcode & 0b000000'10000'00001'00000'0000000000'0) return Instruction(opcode); + break; + + case Operation::mtfsfix: + if(opcode & 0b000000'00011'11111'00001'0000000000'0) return Instruction(opcode); + break; + + case Operation::mtsr: + if(opcode & 0b000000'00000'10000'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::mtsrin: + if(opcode & 0b000000'00000'11111'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::mulhdx: case Operation::mulhdux: + case Operation::mulhwx: case Operation::mulhwux: + if(opcode & 0b000000'00000'00000'00000'1000000000'0) return Instruction(opcode); + break; + + case Operation::sc: + if(opcode & 0b000000'11111'11111'11111'1111111110'1) return Instruction(opcode); + break; + + case Operation::slbie: + case Operation::tlbie: + if(opcode & 0b000000'11111'11111'00000'0000000000'1) return Instruction(opcode); + break; + + case Operation::stwcx_: + if(!(opcode & 0b000000'00000'00000'00000'0000000000'1)) return Instruction(opcode); + break; + + case Operation::clcs: + if(opcode & 0b000000'00000'00000'11111'0000000000'1) return Instruction(opcode); + break; + + case Operation::addx: case Operation::addcx: case Operation::addex: + case Operation::addi: case Operation::addic: case Operation::addic_: + case Operation::addis: + case Operation::andx: case Operation::andcx: + case Operation::andi_: case Operation::andis_: + case Operation::bx: case Operation::bcx: + case Operation::divdx: case Operation::divdux: + case Operation::divwx: case Operation::divwux: + case Operation::eqvx: + case Operation::fmaddx: case Operation::fmaddsx: + case Operation::fmsubx: case Operation::fmsubsx: + case Operation::fnmaddx: case Operation::fnmaddsx: + case Operation::fnmsubx: case Operation::fnmsubsx: + case Operation::fselx: + case Operation::lbz: case Operation::lbzu: + case Operation::lfd: case Operation::lfdu: + case Operation::lfs: case Operation::lfsu: + case Operation::lha: case Operation::lhau: + case Operation::lhz: case Operation::lhzu: + case Operation::lmw: case Operation::lwa: + case Operation::lwz: case Operation::lwzu: + case Operation::mulld: case Operation::mulli: case Operation::mullwx: + case Operation::nandx: case Operation::norx: + case Operation::orx: case Operation::orcx: + case Operation::ori: case Operation::oris: + case Operation::rlwimix: case Operation::rlwinmx: case Operation::rlwnmx: + case Operation::sldx: case Operation::slwx: + case Operation::sradx: case Operation::sradix: + case Operation::srawx: case Operation::srawix: + case Operation::srdx: case Operation::srwx: + case Operation::stb: case Operation::stbu: + case Operation::std: case Operation::stdcx_: case Operation::stdu: + case Operation::stfd: case Operation::stfdu: + case Operation::stfs: case Operation::stfsu: + case Operation::sth: case Operation::sthu: + case Operation::stmw: + case Operation::stw: case Operation::stwu: + case Operation::subfx: case Operation::subfcx: case Operation::subfex: + case Operation::subfic: + case Operation::tdi: case Operation::twi: + case Operation::xorx: case Operation::xori: case Operation::xoris: + + // TODO: ld ldu + // TODO: rldclx rldcrx rldicx rldicrx rldimix + + break; + } + return Instruction(operation, opcode, is_supervisor); } @@ -338,7 +535,7 @@ Instruction Decoder::decode(uint32_t opcode) { return Instruction(opcode); } - // std and stdu + // std and stdu [TODO: or ld and ldu?] switch(opcode & 0b111111'00'00000000'00000000'000000'11) { case 0b111110'00'00000000'00000000'000000'00: return instruction(opcode); case 0b111110'00'00000000'00000000'000000'01: diff --git a/InstructionSets/PowerPC/Instruction.hpp b/InstructionSets/PowerPC/Instruction.hpp index 3fde025d3..c6311e0a0 100644 --- a/InstructionSets/PowerPC/Instruction.hpp +++ b/InstructionSets/PowerPC/Instruction.hpp @@ -192,7 +192,7 @@ enum class Operation: uint8_t { /// Shift right extended with MQ. /// sreq sreq. - /// rA(), rB(), rB() [rc()] + /// rA(), rS(), rB() [rc()] sreqx, /// Shift right immediate with MQ. diff --git a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm index 538a4c51a..5031e616e 100644 --- a/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm +++ b/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm @@ -138,7 +138,7 @@ NSString *offset(Instruction instruction) { NSString *const wholeFile = [[NSString alloc] initWithData:testData encoding:NSUTF8StringEncoding]; NSArray *const lines = [wholeFile componentsSeparatedByString:@"\n"]; - InstructionSet::PowerPC::Decoder decoder; + InstructionSet::PowerPC::Decoder decoder; for(NSString *const line in lines) { // Ignore empty lines and comments. if([line length] == 0) { @@ -156,8 +156,6 @@ NSString *offset(Instruction instruction) { NSString *const operation = columns[2]; const auto instruction = decoder.decode(opcode); - NSLog(@"%@", line); - // Deal with some of the simplified mnemonics as special cases; // underlying observation: distinguishing special cases isn't that // important to a mere decoder. @@ -193,6 +191,10 @@ NSString *offset(Instruction instruction) { NSAssert(FALSE, @"Didn't handle %@", line); break; + case Operation::Undefined: + XCTAssertEqualObjects(operation, @"dc.l"); + break; + case Operation::rlwimix: { // This maps the opposite way from most of the other tests // owing to the simplified names being a shade harder to @@ -362,6 +364,12 @@ NSString *offset(Instruction instruction) { AssertEqualR(columns[4], instruction.rB()); break; + case Operation::clcs: + AssertEqualOperationName(operation, @"clcs"); + AssertEqualR(columns[3], instruction.rD()); + AssertEqualR(columns[4], instruction.rA()); + break; + case Operation::mtsr: AssertEqualOperationName(operation, @"mtsr"); XCTAssertEqual([columns[3] intValue], instruction.sr()); @@ -393,6 +401,15 @@ NSString *offset(Instruction instruction) { XCTAssertEqual([columns[5] hexInt], instruction.nb()); break; + case Operation::rlmix: + AssertEqualOperationNameE(operation, @"rlmix", instruction); + AssertEqualR(columns[3], instruction.rA()); + AssertEqualR(columns[4], instruction.rS()); + AssertEqualR(columns[5], instruction.rB()); + XCTAssertEqual([columns[6] intValue], instruction.mb()); + XCTAssertEqual([columns[7] intValue], instruction.me()); + break; + case Operation::cmp: if([operation isEqualToString:@"cmpw"]) { XCTAssertFalse(instruction.l()); @@ -488,13 +505,24 @@ NSString *offset(Instruction instruction) { #undef Shift - case Operation::srawix: - AssertEqualOperationNameE(operation, @"srawix", instruction); - AssertEqualR(columns[3], instruction.rA()); - AssertEqualR(columns[4], instruction.rS()); - XCTAssertEqual([columns[5] hexInt], instruction.sh()); + +#define ASsh(x) \ + case Operation::x: \ + AssertEqualOperationNameE(operation, @#x, instruction); \ + AssertEqualR(columns[3], instruction.rA()); \ + AssertEqualR(columns[4], instruction.rS()); \ + XCTAssertEqual([columns[5] hexInt], instruction.sh()); \ break; + ASsh(sliqx); + ASsh(slliqx); + ASsh(sraiqx); + ASsh(sriqx); + ASsh(srliqx); + ASsh(srawix); + +#undef ASsh + #define CRMod(x) \ case Operation::x: \ AssertEqualOperationName(operation, @#x); \ @@ -534,12 +562,13 @@ NSString *offset(Instruction instruction) { XCTAssertEqual([columns[5] hexInt], instruction.simm()); \ } break; - ArithImm(mulli); - ArithImm(subfic); + ArithImm(dozi); ArithImm(addi); ArithImm(addic); ArithImm(addic_); ArithImm(addis); + ArithImm(mulli); + ArithImm(subfic); #undef ArithImm @@ -625,6 +654,20 @@ NSString *offset(Instruction instruction) { AssertEqualR(columns[5], instruction.rB()); \ break; + ASB(maskgx); + ASB(maskirx); + ASB(rribx); + ASB(slex); + ASB(sleqx); + ASB(sllqx); + ASB(slqx); + ASB(sraqx); + ASB(srex); + ASB(sreax); + ASB(sreqx); + ASB(srlqx); + ASB(srqx); + ASB(andx); ASB(andcx); ASB(norx);