From db50b0fe23b5202e552b6194a12a01b800c24b3b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 31 Dec 2020 16:51:31 -0500 Subject: [PATCH] Gets started on 6+10 decoding, places stake as to other fields. --- Processors/Decoders/PowerPC/PowerPC.cpp | 44 ++++++++++++++++++++++++- Processors/Decoders/PowerPC/PowerPC.hpp | 38 +++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/Processors/Decoders/PowerPC/PowerPC.cpp b/Processors/Decoders/PowerPC/PowerPC.cpp index e21c900c7..5b751220e 100644 --- a/Processors/Decoders/PowerPC/PowerPC.cpp +++ b/Processors/Decoders/PowerPC/PowerPC.cpp @@ -32,7 +32,8 @@ Instruction Decoder::decode(uint32_t opcode) { if(condition()) return Instruction(Operation::operation, opcode); \ return Instruction(opcode); -#define Six(x) (unsigned(x) << 26) +#define Six(x) (unsigned(x) << 26) +#define SixTen(x, y) (Six(x) | (y << 1)) // First pass: weed out all those instructions identified entirely by the // top six bits. @@ -73,6 +74,47 @@ Instruction Decoder::decode(uint32_t opcode) { Bind(Six(0b001010), cmpli); Bind(Six(0b001011), cmpi); } + // Second pass: all those with a top six bits and a bottom nine or ten. + switch(opcode & SixTen(0b111111, 0b1111111111)) { + default: break; + + BindConditional(is64bit, SixTen(0b011111, 0b0000001001), mulhdux); + BindConditional(is64bit, SixTen(0b011111, 0b0000010101), ldx); + BindConditional(is64bit, SixTen(0b011111, 0b0000011011), sldx); + + Bind(SixTen(0b010011, 0b0000000000), mcrf); + Bind(SixTen(0b010011, 0b0000010000), bclrx); + Bind(SixTen(0b010011, 0b0000100001), crnor); + Bind(SixTen(0b010011, 0b0000110010), rfi); + Bind(SixTen(0b010011, 0b0010000001), crandc); + Bind(SixTen(0b010011, 0b0010010110), isync); + Bind(SixTen(0b010011, 0b0011000001), crxor); + Bind(SixTen(0b010011, 0b0011100001), crnand); + Bind(SixTen(0b010011, 0b0100000001), crand); + Bind(SixTen(0b010011, 0b0100100001), creqv); + Bind(SixTen(0b010011, 0b0110100001), crorc); + Bind(SixTen(0b010011, 0b0111000001), cror); + Bind(SixTen(0b010011, 0b1000010000), bcctrx); + Bind(SixTen(0b011111, 0b0000000000), cmp); + Bind(SixTen(0b011111, 0b0000000100), tw); + Bind(SixTen(0b011111, 0b0000001000), subfcx); Bind(SixTen(0b011111, 0b1000001000), subfcx); + Bind(SixTen(0b011111, 0b0000001010), addcx); Bind(SixTen(0b011111, 0b1000001010), addcx); + Bind(SixTen(0b011111, 0b0000001011), mulhwux); + Bind(SixTen(0b011111, 0b0000010011), mfcr); + Bind(SixTen(0b011111, 0b0000010100), lwarx); + Bind(SixTen(0b011111, 0b0000010111), lwzx); + Bind(SixTen(0b011111, 0b0000011000), slwx); + Bind(SixTen(0b011111, 0b0000011010), cntlzwx); + Bind(SixTen(0b011111, 0b0000011100), andx); + Bind(SixTen(0b011111, 0b0000100000), cmpl); + Bind(SixTen(0b011111, 0b0000101000), subfx); Bind(SixTen(0b011111, 0b1000101000), subfx); + } + + // 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 Bind diff --git a/Processors/Decoders/PowerPC/PowerPC.hpp b/Processors/Decoders/PowerPC/PowerPC.hpp index f9f7e9761..19aae5f1d 100644 --- a/Processors/Decoders/PowerPC/PowerPC.hpp +++ b/Processors/Decoders/PowerPC/PowerPC.hpp @@ -55,9 +55,16 @@ enum class Operation: uint8_t { fresx, frsqrtex, fselx, fsqrtx, frsqrtsx, slbia, slbie, // 64-bit only PowerPC instructions. - cntlzdx, divdx, divdux, extswx, fcfidx, fctidx, fctidzx, tdi + cntlzdx, divdx, divdux, extswx, fcfidx, fctidx, fctidzx, tdi, mulhdux, ldx, + sldx }; +/*! + Holds a decoded PowerPC instruction. + + Implementation note: because the PowerPC encoding is particularly straightforward, + only the operation has been decoded ahead of time; all other fields are decoded on-demand. +*/ struct Instruction { const Operation operation = Operation::Undefined; const uint32_t opcode = 0; @@ -65,7 +72,34 @@ struct Instruction { Instruction(uint32_t opcode) : opcode(opcode) {} Instruction(Operation operation, uint32_t opcode) : operation(operation), opcode(opcode) {} - // TODO: all field decoding here. + // Instruction fields are decoded below; naming is as directly dictated by + // Motorola's documentation, and the definitions below are sorted by synonym. + uint16_t uimm() { return uint16_t(opcode & 0xffff); } + int16_t simm() { return int16_t(opcode & 0xffff); } + + int to() { return (opcode >> 21) & 0x1f; } + int d() { return (opcode >> 21) & 0x1f; } + int bo() { return (opcode >> 21) & 0x1f; } + int crbD() { return (opcode >> 21) & 0x1f; } + int s() { return (opcode >> 21) & 0x1f; } + + int a() { return (opcode >> 16) & 0x1f; } + int bi() { return (opcode >> 16) & 0x1f; } + int crbA() { return (opcode >> 16) & 0x1f; } + + int b() { return (opcode >> 11) & 0x1f; } + int crbB() { return (opcode >> 11) & 0x1f; } + + int crfd() { return (opcode >> 23) & 0x07; } + + int bd() { return (opcode >> 2) & 0x3fff; } + + int li() { return (opcode >> 2) & 0x0fff; } + + // Various single bit fields. + int l() { return (opcode >> 21) & 0x01; } + int aa() { return (opcode >> 1) & 0x01; } + int lk() { return opcode & 0x01; } }; struct Decoder {