mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-07 23:29:06 +00:00
Build in an optional post hoc validation.
TODO: validate.
This commit is contained in:
parent
ac524532e7
commit
d23c714ec7
@ -10,9 +10,23 @@
|
|||||||
|
|
||||||
using namespace InstructionSet::PowerPC;
|
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:
|
// Quick bluffer's guide to PowerPC instruction encoding:
|
||||||
//
|
//
|
||||||
// There is a six-bit field at the very top of the instruction.
|
// 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
|
// currently check the value of reserved bits. That may need to change
|
||||||
// if/when I add support for extended instruction sets.
|
// if/when I add support for extended instruction sets.
|
||||||
|
|
||||||
#define Bind(mask, operation) case mask: return Instruction(Operation::operation, opcode);
|
#define Bind(mask, operation) case mask: return instruction<model, validate_reserved_bits, Operation::operation>(opcode);
|
||||||
#define BindSupervisor(mask, operation) case mask: return Instruction(Operation::operation, opcode, true);
|
#define BindSupervisor(mask, operation) case mask: return instruction<model, validate_reserved_bits, Operation::operation>(opcode, true);
|
||||||
#define BindConditional(condition, mask, operation) \
|
#define BindConditional(condition, mask, operation) \
|
||||||
case mask: \
|
case mask: \
|
||||||
if(condition(model_)) return Instruction(Operation::operation, opcode); \
|
if(condition(model)) return instruction<model, validate_reserved_bits, Operation::operation>(opcode); \
|
||||||
return Instruction(opcode);
|
return instruction<model, validate_reserved_bits, Operation::operation>(opcode);
|
||||||
#define BindSupervisorConditional(condition, mask, operation) \
|
#define BindSupervisorConditional(condition, mask, operation) \
|
||||||
case mask: \
|
case mask: \
|
||||||
if(condition(model_)) return Instruction(Operation::operation, opcode, true); \
|
if(condition(model)) return instruction<model, validate_reserved_bits, Operation::operation>(opcode, true); \
|
||||||
return Instruction(opcode);
|
return instruction<model, validate_reserved_bits, Operation::operation>(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))
|
||||||
@ -64,7 +78,7 @@ Instruction Decoder::decode(uint32_t opcode) {
|
|||||||
case 0: case 1: case 2: case 3: case 4: case 5:
|
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 8: case 9: case 10: case 11: case 12: case 13:
|
||||||
case 16: case 17: case 18: case 19: case 20:
|
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);
|
default: return Instruction(opcode);
|
||||||
}
|
}
|
||||||
@ -318,26 +332,26 @@ Instruction Decoder::decode(uint32_t opcode) {
|
|||||||
|
|
||||||
// stwcx. and stdcx.
|
// stwcx. and stdcx.
|
||||||
switch(opcode & 0b111111'0000'0000'0000'0000'111111111'1) {
|
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:
|
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);
|
return Instruction(opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// std and stdu
|
// std and stdu
|
||||||
switch(opcode & 0b111111'00'00000000'00000000'000000'11) {
|
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:
|
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);
|
return Instruction(opcode);
|
||||||
case 0b111010'00'00000000'00000000'000000'10:
|
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);
|
return Instruction(opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sc
|
// sc
|
||||||
if((opcode & 0b111111'00'00000000'00000000'000000'1'0) == 0b010001'00'00000000'00000000'000000'1'0) {
|
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
|
#undef Six
|
||||||
@ -348,3 +362,11 @@ Instruction Decoder::decode(uint32_t opcode) {
|
|||||||
|
|
||||||
return Instruction(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>;
|
||||||
|
@ -38,16 +38,16 @@ constexpr bool is601(Model model) {
|
|||||||
/*!
|
/*!
|
||||||
Implements PowerPC instruction decoding.
|
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 {
|
template <Model model, bool validate_reserved_bits = false> struct Decoder {
|
||||||
public:
|
Instruction decode(uint32_t opcode);
|
||||||
Decoder(Model model);
|
|
||||||
|
|
||||||
Instruction decode(uint32_t opcode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Model model_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ NSString *offset(Instruction instruction) {
|
|||||||
NSString *const wholeFile = [[NSString alloc] initWithData:testData encoding:NSUTF8StringEncoding];
|
NSString *const wholeFile = [[NSString alloc] initWithData:testData encoding:NSUTF8StringEncoding];
|
||||||
NSArray<NSString *> *const lines = [wholeFile componentsSeparatedByString:@"\n"];
|
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) {
|
for(NSString *const line in lines) {
|
||||||
// Ignore empty lines and comments.
|
// Ignore empty lines and comments.
|
||||||
if([line length] == 0) {
|
if([line length] == 0) {
|
||||||
|
@ -119,7 +119,7 @@ namespace {
|
|||||||
// MARK: - Decoder
|
// MARK: - Decoder
|
||||||
|
|
||||||
- (void)decode:(const uint32_t *)stream {
|
- (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++) {
|
for(int c = 0; c < 32; c++) {
|
||||||
instructions[c] = decoder.decode(stream[c]);
|
instructions[c] = decoder.decode(stream[c]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user