From ebfa35c2c7a7c341078fe8fb01a9bc68e03cd40b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 31 Dec 2020 18:14:38 -0500 Subject: [PATCH] Conquers another page of instructions; adds supervisor flag. --- Processors/Decoders/PowerPC/PowerPC.cpp | 73 ++++++++++++++++++++++++- Processors/Decoders/PowerPC/PowerPC.hpp | 15 ++++- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Processors/Decoders/PowerPC/PowerPC.cpp b/Processors/Decoders/PowerPC/PowerPC.cpp index 5b751220e..8c908ffa9 100644 --- a/Processors/Decoders/PowerPC/PowerPC.cpp +++ b/Processors/Decoders/PowerPC/PowerPC.cpp @@ -26,11 +26,16 @@ Instruction Decoder::decode(uint32_t opcode) { // // I've decided to hew directly to the mnemonics. -#define Bind(mask, operation) case mask: return Instruction(Operation::operation, opcode); +#define Bind(mask, operation) case mask: return Instruction(Operation::operation, opcode); +#define BindSupervisor(mask, operation) case mask: return Instruction(Operation::operation, opcode, true); #define BindConditional(condition, mask, operation) \ case mask: \ if(condition()) return Instruction(Operation::operation, opcode); \ return Instruction(opcode); +#define BindSupervisorConditional(condition, mask, operation) \ + case mask: \ + if(condition()) return Instruction(Operation::operation, opcode, true); \ + return Instruction(opcode); #define Six(x) (unsigned(x) << 26) #define SixTen(x, y) (Six(x) | (y << 1)) @@ -81,6 +86,19 @@ Instruction Decoder::decode(uint32_t opcode) { BindConditional(is64bit, SixTen(0b011111, 0b0000001001), mulhdux); BindConditional(is64bit, SixTen(0b011111, 0b0000010101), ldx); BindConditional(is64bit, SixTen(0b011111, 0b0000011011), sldx); + BindConditional(is64bit, SixTen(0b011111, 0b0000110101), ldux); + BindConditional(is64bit, SixTen(0b011111, 0b0000111010), cntlzdx); + BindConditional(is64bit, SixTen(0b011111, 0b0001000100), td); + BindConditional(is64bit, SixTen(0b011111, 0b0001001001), mulhdx); + BindConditional(is64bit, SixTen(0b011111, 0b0001010100), ldarx); + BindConditional(is64bit, SixTen(0b011111, 0b0010010101), stdx); + BindConditional(is64bit, SixTen(0b011111, 0b0010110101), stdux); + BindConditional(is64bit, SixTen(0b011111, 0b0011101001), mulld); BindConditional(is64bit, SixTen(0b011111, 0b1011101001), mulld); + BindConditional(is64bit, SixTen(0b011111, 0b0101010101), lwax); + BindConditional(is64bit, SixTen(0b011111, 0b0101110101), lwaux); +// BindConditional(is64bit, SixTen(0b011111, 0b1100111011), sradix); // TODO: encoding is unclear re: the sh flag. + BindConditional(is64bit, SixTen(0b011111, 0b0110110010), slbie); + BindConditional(is64bit, SixTen(0b011111, 0b0111001001), divdux); BindConditional(is64bit, SixTen(0b011111, 0b1111001001), divdux); Bind(SixTen(0b010011, 0b0000000000), mcrf); Bind(SixTen(0b010011, 0b0000010000), bclrx); @@ -108,14 +126,67 @@ Instruction Decoder::decode(uint32_t opcode) { Bind(SixTen(0b011111, 0b0000011100), andx); Bind(SixTen(0b011111, 0b0000100000), cmpl); Bind(SixTen(0b011111, 0b0000101000), subfx); Bind(SixTen(0b011111, 0b1000101000), subfx); + Bind(SixTen(0b011111, 0b0000110110), dcbst); + Bind(SixTen(0b011111, 0b0000110111), lwzux); + Bind(SixTen(0b011111, 0b0000111100), andcx); + Bind(SixTen(0b011111, 0b0001001011), mulhwx); + Bind(SixTen(0b011111, 0b0001010011), mfmsr); + Bind(SixTen(0b011111, 0b0001010110), dcbf); + Bind(SixTen(0b011111, 0b0001010111), lbzx); + Bind(SixTen(0b011111, 0b0001101000), negx); Bind(SixTen(0b011111, 0b1001101000), negx); + Bind(SixTen(0b011111, 0b0001110111), lbzux); + Bind(SixTen(0b011111, 0b0001111100), norx); + Bind(SixTen(0b011111, 0b0010001000), subfex); Bind(SixTen(0b011111, 0b1010001000), subfex); + Bind(SixTen(0b011111, 0b0010001010), addex); Bind(SixTen(0b011111, 0b1010001010), addex); + Bind(SixTen(0b011111, 0b0010010000), mtcrf); + Bind(SixTen(0b011111, 0b0010010010), mtmsr); + Bind(SixTen(0b011111, 0b0010010111), stwx); + Bind(SixTen(0b011111, 0b0010110111), stwux); + Bind(SixTen(0b011111, 0b0011001000), subfzex); Bind(SixTen(0b011111, 0b1011001000), subfzex); + Bind(SixTen(0b011111, 0b0011001010), addzex); Bind(SixTen(0b011111, 0b1011001010), addzex); + Bind(SixTen(0b011111, 0b0011010111), stbx); + Bind(SixTen(0b011111, 0b0011101000), subfmex); Bind(SixTen(0b011111, 0b1011101000), subfmex); + Bind(SixTen(0b011111, 0b0011101010), addmex); Bind(SixTen(0b011111, 0b1011101010), addmex); + Bind(SixTen(0b011111, 0b0011101011), mullwx); Bind(SixTen(0b011111, 0b1011101011), mullwx); + Bind(SixTen(0b011111, 0b0011110110), dcbtst); + Bind(SixTen(0b011111, 0b0011110111), stbux); + Bind(SixTen(0b011111, 0b0100001010), addx); Bind(SixTen(0b011111, 0b1100001010), addx); + Bind(SixTen(0b011111, 0b0100010110), dcbt); + Bind(SixTen(0b011111, 0b0100010111), lhzx); + Bind(SixTen(0b011111, 0b0100011100), eqvx); + Bind(SixTen(0b011111, 0b0100110110), eciwx); + Bind(SixTen(0b011111, 0b0100110111), lhzux); + Bind(SixTen(0b011111, 0b0100111100), xorx); + Bind(SixTen(0b011111, 0b0101010111), lhax); + Bind(SixTen(0b011111, 0b0101110011), mftb); + Bind(SixTen(0b011111, 0b0101110111), lhaux); + Bind(SixTen(0b011111, 0b0110010111), sthx); + Bind(SixTen(0b011111, 0b0110011100), orcx); + Bind(SixTen(0b011111, 0b0110110110), ecowx); + Bind(SixTen(0b011111, 0b0110110111), sthux); + Bind(SixTen(0b011111, 0b0110111100), orx); + Bind(SixTen(0b011111, 0b0111001011), divwux); Bind(SixTen(0b011111, 0b1111001011), divwux); + Bind(SixTen(0b011111, 0b0111010110), dcbi); + + Bind(SixTen(0b011111, 0b0101010011), mfspr); // Flagged as "supervisor and user"? + Bind(SixTen(0b011111, 0b0111010011), mtspr); // Flagged as "supervisor and user"? + + BindSupervisorConditional(is32bit, SixTen(0b011111, 0b0011010010), mtsr); + BindSupervisorConditional(is32bit, SixTen(0b011111, 0b0011110010), mtsrin); + + BindSupervisor(SixTen(0b011111, 0b0100110010), tlbie); // TODO: mark formally as optional? + BindSupervisor(SixTen(0b011111, 0b0101110010), tlbia); // TODO: mark formally as optional? } + // TODO: stwcx., stdcx. + // Check for sc. if((opcode & 0b010001'00000'00000'00000000000000'1'0) == 0b010001'00000'00000'00000000000000'1'0) { return Instruction(Operation::sc, opcode); } #undef Six +#undef SixTen #undef Bind #undef BindConditional diff --git a/Processors/Decoders/PowerPC/PowerPC.hpp b/Processors/Decoders/PowerPC/PowerPC.hpp index 19aae5f1d..0cdb2c8ab 100644 --- a/Processors/Decoders/PowerPC/PowerPC.hpp +++ b/Processors/Decoders/PowerPC/PowerPC.hpp @@ -46,17 +46,20 @@ enum class Operation: uint8_t { sc, slwx, srawx, srawix, srwx, stb, stbu, stbux, stbx, stfd, stfdu, stfdux, stfdx, stfs, stfsu, stfsux, stfsx, sth, sthbrx, sthu, sthux, sthx, stmw, stswi, stswx, stw, stwbrx, stwcx_, stwu, stwux, stwx, subfx, subfcx, - subfex, subfic, subfmex, subfzex, sync, tlbie, tw, twi, xorx, xori, xoris, + subfex, subfic, subfmex, subfzex, sync, tw, twi, xorx, xori, xoris, mftb, // 32-bit, supervisor level. dcbi, + // Supervisor, optional. + tlbia, tlbie, + // Optional. fresx, frsqrtex, fselx, fsqrtx, frsqrtsx, slbia, slbie, // 64-bit only PowerPC instructions. cntlzdx, divdx, divdux, extswx, fcfidx, fctidx, fctidzx, tdi, mulhdux, ldx, - sldx + sldx, ldux, td, mulhdx, ldarx, stdx, stdux, mulld, lwax, lwaux, sradix, }; /*! @@ -67,10 +70,11 @@ enum class Operation: uint8_t { */ struct Instruction { const Operation operation = Operation::Undefined; + const bool is_supervisor = false; const uint32_t opcode = 0; Instruction(uint32_t opcode) : opcode(opcode) {} - Instruction(Operation operation, uint32_t opcode) : operation(operation), opcode(opcode) {} + Instruction(Operation operation, uint32_t opcode, bool is_supervisor = false) : operation(operation), is_supervisor(is_supervisor), opcode(opcode) {} // Instruction fields are decoded below; naming is as directly dictated by // Motorola's documentation, and the definitions below are sorted by synonym. @@ -100,6 +104,7 @@ struct Instruction { int l() { return (opcode >> 21) & 0x01; } int aa() { return (opcode >> 1) & 0x01; } int lk() { return opcode & 0x01; } + int rc() { return opcode & 0x01; } }; struct Decoder { @@ -115,6 +120,10 @@ struct Decoder { return false; } + bool is32bit() { + return true; + } + bool is601() { return model_ == Model::MPC601; }