1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-09 00:37:27 +00:00

Gets started on 6+10 decoding, places stake as to other fields.

This commit is contained in:
Thomas Harte 2020-12-31 16:51:31 -05:00
parent 233a69a1d8
commit db50b0fe23
2 changed files with 79 additions and 3 deletions

View File

@ -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

View File

@ -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 {