1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Build in an optional post hoc validation.

TODO: validate.
This commit is contained in:
Thomas Harte 2022-04-05 11:23:54 -04:00
parent ac524532e7
commit d23c714ec7
4 changed files with 48 additions and 26 deletions

View File

@ -10,9 +10,23 @@
using namespace InstructionSet::PowerPC;
Decoder::Decoder(Model model) : model_(model) {}
namespace {
Instruction Decoder::decode(uint32_t opcode) {
template <Model model, bool validate_reserved_bits, Operation operation> Instruction instruction(uint32_t opcode, bool is_supervisor = false) {
// If validation isn't required, there's nothing to do here.
if constexpr (!validate_reserved_bits) {
return Instruction(operation, opcode, is_supervisor);
}
// Otherwise, validation depends on operation
// (and, in principle, processor model).
return Instruction(operation, opcode, is_supervisor);
}
}
template <Model model, bool validate_reserved_bits>
Instruction Decoder<model, validate_reserved_bits>::decode(uint32_t opcode) {
// Quick bluffer's guide to PowerPC instruction encoding:
//
// There is a six-bit field at the very top of the instruction.
@ -32,16 +46,16 @@ Instruction Decoder::decode(uint32_t opcode) {
// currently check the value of reserved bits. That may need to change
// if/when I add support for extended instruction sets.
#define Bind(mask, operation) case mask: return Instruction(Operation::operation, opcode);
#define BindSupervisor(mask, operation) case mask: return Instruction(Operation::operation, opcode, true);
#define Bind(mask, operation) case mask: return instruction<model, validate_reserved_bits, Operation::operation>(opcode);
#define BindSupervisor(mask, operation) case mask: return instruction<model, validate_reserved_bits, Operation::operation>(opcode, true);
#define BindConditional(condition, mask, operation) \
case mask: \
if(condition(model_)) return Instruction(Operation::operation, opcode); \
return Instruction(opcode);
if(condition(model)) return instruction<model, validate_reserved_bits, Operation::operation>(opcode); \
return instruction<model, validate_reserved_bits, Operation::operation>(opcode);
#define BindSupervisorConditional(condition, mask, operation) \
case mask: \
if(condition(model_)) return Instruction(Operation::operation, opcode, true); \
return Instruction(opcode);
if(condition(model)) return instruction<model, validate_reserved_bits, Operation::operation>(opcode, true); \
return instruction<model, validate_reserved_bits, Operation::operation>(opcode);
#define Six(x) (unsigned(x) << 26)
#define SixTen(x, y) (Six(x) | ((y) << 1))
@ -64,7 +78,7 @@ Instruction Decoder::decode(uint32_t opcode) {
case 0: case 1: case 2: case 3: case 4: case 5:
case 8: case 9: case 10: case 11: case 12: case 13:
case 16: case 17: case 18: case 19: case 20:
return Instruction(Operation::bcx, opcode);
return instruction<model, validate_reserved_bits, Operation::bcx>(opcode);
default: return Instruction(opcode);
}
@ -318,26 +332,26 @@ Instruction Decoder::decode(uint32_t opcode) {
// stwcx. and stdcx.
switch(opcode & 0b111111'0000'0000'0000'0000'111111111'1) {
case 0b011111'0000'0000'0000'0000'010010110'1: return Instruction(Operation::stwcx_, opcode);
case 0b011111'0000'0000'0000'0000'010010110'1: return instruction<model, validate_reserved_bits, Operation::stwcx_>(opcode);
case 0b011111'0000'0000'0000'0000'011010110'1:
if(is64bit(model_)) return Instruction(Operation::stdcx_, opcode);
if(is64bit(model)) return instruction<model, validate_reserved_bits, Operation::stdcx_>(opcode);
return Instruction(opcode);
}
// std and stdu
switch(opcode & 0b111111'00'00000000'00000000'000000'11) {
case 0b111110'00'00000000'00000000'000000'00: return Instruction(Operation::std, opcode);
case 0b111110'00'00000000'00000000'000000'00: return instruction<model, validate_reserved_bits, Operation::std>(opcode);
case 0b111110'00'00000000'00000000'000000'01:
if(is64bit(model_)) return Instruction(Operation::stdu, opcode);
if(is64bit(model)) return instruction<model, validate_reserved_bits, Operation::stdu>(opcode);
return Instruction(opcode);
case 0b111010'00'00000000'00000000'000000'10:
if(is64bit(model_)) return Instruction(Operation::lwa, opcode);
if(is64bit(model)) return instruction<model, validate_reserved_bits, Operation::lwa>(opcode);
return Instruction(opcode);
}
// sc
if((opcode & 0b111111'00'00000000'00000000'000000'1'0) == 0b010001'00'00000000'00000000'000000'1'0) {
return Instruction(Operation::sc, opcode);
return instruction<model, validate_reserved_bits, Operation::sc>(opcode);
}
#undef Six
@ -348,3 +362,11 @@ Instruction Decoder::decode(uint32_t opcode) {
return Instruction(opcode);
}
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC601, true>;
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC603, true>;
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC620, true>;
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC601, false>;
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC603, false>;
template class InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC620, false>;

View File

@ -38,16 +38,16 @@ constexpr bool is601(Model model) {
/*!
Implements PowerPC instruction decoding.
This is an experimental implementation; it has not yet undergone significant testing.
@c model Indicates the instruction set to decode.
@c validate_reserved_bits If set to @c true, check that all
reserved bits are 0 and produce an invalid opcode if not. Otherwise does no
inspection of reserved bits.
TODO: determine what specific models of PowerPC do re: reserved bits.
*/
struct Decoder {
public:
Decoder(Model model);
Instruction decode(uint32_t opcode);
private:
Model model_;
template <Model model, bool validate_reserved_bits = false> struct Decoder {
Instruction decode(uint32_t opcode);
};
}

View File

@ -138,7 +138,7 @@ NSString *offset(Instruction instruction) {
NSString *const wholeFile = [[NSString alloc] initWithData:testData encoding:NSUTF8StringEncoding];
NSArray<NSString *> *const lines = [wholeFile componentsSeparatedByString:@"\n"];
InstructionSet::PowerPC::Decoder decoder(InstructionSet::PowerPC::Model::MPC601);
InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC601> decoder;
for(NSString *const line in lines) {
// Ignore empty lines and comments.
if([line length] == 0) {

View File

@ -119,7 +119,7 @@ namespace {
// MARK: - Decoder
- (void)decode:(const uint32_t *)stream {
InstructionSet::PowerPC::Decoder decoder(InstructionSet::PowerPC::Model::MPC601);
InstructionSet::PowerPC::Decoder<InstructionSet::PowerPC::Model::MPC601> decoder;
for(int c = 0; c < 32; c++) {
instructions[c] = decoder.decode(stream[c]);
}