1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Conquers another page of instructions; adds supervisor flag.

This commit is contained in:
Thomas Harte 2020-12-31 18:14:38 -05:00
parent db50b0fe23
commit ebfa35c2c7
2 changed files with 84 additions and 4 deletions

View File

@ -26,11 +26,16 @@ Instruction Decoder::decode(uint32_t opcode) {
// //
// I've decided to hew directly to the mnemonics. // 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) \ #define BindConditional(condition, mask, operation) \
case mask: \ case mask: \
if(condition()) return Instruction(Operation::operation, opcode); \ if(condition()) return Instruction(Operation::operation, opcode); \
return Instruction(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 Six(x) (unsigned(x) << 26)
#define SixTen(x, y) (Six(x) | (y << 1)) #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, 0b0000001001), mulhdux);
BindConditional(is64bit, SixTen(0b011111, 0b0000010101), ldx); BindConditional(is64bit, SixTen(0b011111, 0b0000010101), ldx);
BindConditional(is64bit, SixTen(0b011111, 0b0000011011), sldx); 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, 0b0000000000), mcrf);
Bind(SixTen(0b010011, 0b0000010000), bclrx); Bind(SixTen(0b010011, 0b0000010000), bclrx);
@ -108,14 +126,67 @@ Instruction Decoder::decode(uint32_t opcode) {
Bind(SixTen(0b011111, 0b0000011100), andx); Bind(SixTen(0b011111, 0b0000011100), andx);
Bind(SixTen(0b011111, 0b0000100000), cmpl); Bind(SixTen(0b011111, 0b0000100000), cmpl);
Bind(SixTen(0b011111, 0b0000101000), subfx); Bind(SixTen(0b011111, 0b1000101000), subfx); 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. // Check for sc.
if((opcode & 0b010001'00000'00000'00000000000000'1'0) == 0b010001'00000'00000'00000000000000'1'0) { if((opcode & 0b010001'00000'00000'00000000000000'1'0) == 0b010001'00000'00000'00000000000000'1'0) {
return Instruction(Operation::sc, opcode); return Instruction(Operation::sc, opcode);
} }
#undef Six #undef Six
#undef SixTen
#undef Bind #undef Bind
#undef BindConditional #undef BindConditional

View File

@ -46,17 +46,20 @@ enum class Operation: uint8_t {
sc, slwx, srawx, srawix, srwx, stb, stbu, stbux, stbx, stfd, stfdu, sc, slwx, srawx, srawix, srwx, stb, stbu, stbux, stbx, stfd, stfdu,
stfdux, stfdx, stfs, stfsu, stfsux, stfsx, sth, sthbrx, sthu, sthux, sthx, stfdux, stfdx, stfs, stfsu, stfsux, stfsx, sth, sthbrx, sthu, sthux, sthx,
stmw, stswi, stswx, stw, stwbrx, stwcx_, stwu, stwux, stwx, subfx, subfcx, 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. // 32-bit, supervisor level.
dcbi, dcbi,
// Supervisor, optional.
tlbia, tlbie,
// Optional. // Optional.
fresx, frsqrtex, fselx, fsqrtx, frsqrtsx, slbia, slbie, fresx, frsqrtex, fselx, fsqrtx, frsqrtsx, slbia, slbie,
// 64-bit only PowerPC instructions. // 64-bit only PowerPC instructions.
cntlzdx, divdx, divdux, extswx, fcfidx, fctidx, fctidzx, tdi, mulhdux, ldx, 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 { struct Instruction {
const Operation operation = Operation::Undefined; const Operation operation = Operation::Undefined;
const bool is_supervisor = false;
const uint32_t opcode = 0; const uint32_t opcode = 0;
Instruction(uint32_t opcode) : opcode(opcode) {} 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 // Instruction fields are decoded below; naming is as directly dictated by
// Motorola's documentation, and the definitions below are sorted by synonym. // Motorola's documentation, and the definitions below are sorted by synonym.
@ -100,6 +104,7 @@ struct Instruction {
int l() { return (opcode >> 21) & 0x01; } int l() { return (opcode >> 21) & 0x01; }
int aa() { return (opcode >> 1) & 0x01; } int aa() { return (opcode >> 1) & 0x01; }
int lk() { return opcode & 0x01; } int lk() { return opcode & 0x01; }
int rc() { return opcode & 0x01; }
}; };
struct Decoder { struct Decoder {
@ -115,6 +120,10 @@ struct Decoder {
return false; return false;
} }
bool is32bit() {
return true;
}
bool is601() { bool is601() {
return model_ == Model::MPC601; return model_ == Model::MPC601;
} }