mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 01:30:56 +00:00
Provide full pair for string conversion.
This commit is contained in:
parent
6cecb84878
commit
6dd5628dd6
@ -432,7 +432,7 @@ std::string InstructionSet::x86::to_string(
|
|||||||
|
|
||||||
template<bool is_32bit>
|
template<bool is_32bit>
|
||||||
std::string InstructionSet::x86::to_string(
|
std::string InstructionSet::x86::to_string(
|
||||||
Instruction<is_32bit> instruction,
|
std::pair<int, Instruction<is_32bit>> instruction,
|
||||||
Model model,
|
Model model,
|
||||||
int offset_length,
|
int offset_length,
|
||||||
int immediate_length
|
int immediate_length
|
||||||
@ -440,7 +440,7 @@ std::string InstructionSet::x86::to_string(
|
|||||||
std::string operation;
|
std::string operation;
|
||||||
|
|
||||||
// Add segment override, if any, ahead of some operations that won't otherwise print it.
|
// Add segment override, if any, ahead of some operations that won't otherwise print it.
|
||||||
switch(instruction.operation) {
|
switch(instruction.second.operation) {
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
case Operation::CMPS:
|
case Operation::CMPS:
|
||||||
@ -448,7 +448,7 @@ std::string InstructionSet::x86::to_string(
|
|||||||
case Operation::STOS:
|
case Operation::STOS:
|
||||||
case Operation::LODS:
|
case Operation::LODS:
|
||||||
case Operation::MOVS:
|
case Operation::MOVS:
|
||||||
switch(instruction.segment_override()) {
|
switch(instruction.second.segment_override()) {
|
||||||
default: break;
|
default: break;
|
||||||
case Source::ES: operation += "es "; break;
|
case Source::ES: operation += "es "; break;
|
||||||
case Source::CS: operation += "cs "; break;
|
case Source::CS: operation += "cs "; break;
|
||||||
@ -461,10 +461,10 @@ std::string InstructionSet::x86::to_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a repetition prefix; it'll be one of 'rep', 'repe' or 'repne'.
|
// Add a repetition prefix; it'll be one of 'rep', 'repe' or 'repne'.
|
||||||
switch(instruction.repetition()) {
|
switch(instruction.second.repetition()) {
|
||||||
case Repetition::None: break;
|
case Repetition::None: break;
|
||||||
case Repetition::RepE:
|
case Repetition::RepE:
|
||||||
switch(instruction.operation) {
|
switch(instruction.second.operation) {
|
||||||
case Operation::CMPS:
|
case Operation::CMPS:
|
||||||
case Operation::SCAS:
|
case Operation::SCAS:
|
||||||
operation += "repe ";
|
operation += "repe ";
|
||||||
@ -476,7 +476,7 @@ std::string InstructionSet::x86::to_string(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Repetition::RepNE:
|
case Repetition::RepNE:
|
||||||
switch(instruction.operation) {
|
switch(instruction.second.operation) {
|
||||||
case Operation::CMPS:
|
case Operation::CMPS:
|
||||||
case Operation::SCAS:
|
case Operation::SCAS:
|
||||||
operation += "repne ";
|
operation += "repne ";
|
||||||
@ -490,38 +490,38 @@ std::string InstructionSet::x86::to_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add operation itself.
|
// Add operation itself.
|
||||||
operation += to_string(instruction.operation, instruction.operation_size(), model);
|
operation += to_string(instruction.second.operation, instruction.second.operation_size(), model);
|
||||||
operation += " ";
|
operation += " ";
|
||||||
|
|
||||||
// Deal with a few special cases up front.
|
// Deal with a few special cases up front.
|
||||||
switch(instruction.operation) {
|
switch(instruction.second.operation) {
|
||||||
default: {
|
default: {
|
||||||
const int operands = max_displayed_operands(instruction.operation);
|
const int operands = max_displayed_operands(instruction.second.operation);
|
||||||
const bool displacement = has_displacement(instruction.operation);
|
const bool displacement = has_displacement(instruction.second.operation);
|
||||||
const bool print_first = operands > 1 && instruction.destination().source() != Source::None;
|
const bool print_first = operands > 1 && instruction.second.destination().source() != Source::None;
|
||||||
if(print_first) {
|
if(print_first) {
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length);
|
||||||
}
|
}
|
||||||
if(operands > 0 && instruction.source().source() != Source::None) {
|
if(operands > 0 && instruction.second.source().source() != Source::None) {
|
||||||
if(print_first) operation += ", ";
|
if(print_first) operation += ", ";
|
||||||
operation += to_string(instruction.source(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.source(), instruction.second, offset_length, immediate_length);
|
||||||
}
|
}
|
||||||
if(displacement) {
|
if(displacement) {
|
||||||
operation += to_hex(instruction.displacement(), offset_length);
|
operation += to_hex(instruction.second.displacement(), offset_length);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Operation::CALLfar:
|
case Operation::CALLfar:
|
||||||
case Operation::JMPfar: {
|
case Operation::JMPfar: {
|
||||||
switch(instruction.destination().source()) {
|
switch(instruction.second.destination().source()) {
|
||||||
case Source::Immediate:
|
case Source::Immediate:
|
||||||
operation += to_hex(instruction.segment(), 4, false);
|
operation += to_hex(instruction.second.segment(), 4, false);
|
||||||
operation += "h:";
|
operation += "h:";
|
||||||
operation += to_hex(instruction.offset(), 4, false);
|
operation += to_hex(instruction.second.offset(), 4, false);
|
||||||
operation += "h";
|
operation += "h";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -529,35 +529,35 @@ std::string InstructionSet::x86::to_string(
|
|||||||
case Operation::LDS:
|
case Operation::LDS:
|
||||||
case Operation::LES: // The test set labels the pointer type as dword, which I guess is technically accurate.
|
case Operation::LES: // The test set labels the pointer type as dword, which I guess is technically accurate.
|
||||||
// A full 32 bits will be loaded from that address in 16-bit mode.
|
// A full 32 bits will be loaded from that address in 16-bit mode.
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length);
|
||||||
operation += ", ";
|
operation += ", ";
|
||||||
operation += to_string(instruction.source(), instruction, offset_length, immediate_length, InstructionSet::x86::DataSize::DWord);
|
operation += to_string(instruction.second.source(), instruction.second, offset_length, immediate_length, InstructionSet::x86::DataSize::DWord);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Operation::IN:
|
case Operation::IN:
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length);
|
||||||
operation += ", ";
|
operation += ", ";
|
||||||
switch(instruction.source().source()) {
|
switch(instruction.second.source().source()) {
|
||||||
case Source::DirectAddress:
|
case Source::DirectAddress:
|
||||||
operation += to_hex(uint8_t(instruction.offset()));
|
operation += to_hex(uint8_t(instruction.second.offset()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
operation += to_string(instruction.source(), instruction, offset_length, immediate_length, InstructionSet::x86::DataSize::Word);
|
operation += to_string(instruction.second.source(), instruction.second, offset_length, immediate_length, InstructionSet::x86::DataSize::Word);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Operation::OUT:
|
case Operation::OUT:
|
||||||
switch(instruction.destination().source()) {
|
switch(instruction.second.destination().source()) {
|
||||||
case Source::DirectAddress:
|
case Source::DirectAddress:
|
||||||
operation += to_hex(uint8_t(instruction.offset()));
|
operation += to_hex(uint8_t(instruction.second.offset()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length, InstructionSet::x86::DataSize::Word);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length, InstructionSet::x86::DataSize::Word);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
operation += ", ";
|
operation += ", ";
|
||||||
operation += to_string(instruction.source(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.source(), instruction.second, offset_length, immediate_length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Rolls and shifts list eCX as a source on the understanding that everyone knows that rolls and shifts
|
// Rolls and shifts list eCX as a source on the understanding that everyone knows that rolls and shifts
|
||||||
@ -567,18 +567,18 @@ std::string InstructionSet::x86::to_string(
|
|||||||
case Operation::SAL: case Operation::SAR:
|
case Operation::SAL: case Operation::SAR:
|
||||||
case Operation::SHR:
|
case Operation::SHR:
|
||||||
case Operation::SETMO: case Operation::SETMOC:
|
case Operation::SETMO: case Operation::SETMOC:
|
||||||
operation += to_string(instruction.destination(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.destination(), instruction.second, offset_length, immediate_length);
|
||||||
switch(instruction.source().source()) {
|
switch(instruction.second.source().source()) {
|
||||||
case Source::None: break;
|
case Source::None: break;
|
||||||
case Source::eCX: operation += ", cl"; break;
|
case Source::eCX: operation += ", cl"; break;
|
||||||
case Source::Immediate:
|
case Source::Immediate:
|
||||||
// Providing an immediate operand of 1 is a little future-proofing by the decoder; the '1'
|
// Providing an immediate operand of 1 is a little future-proofing by the decoder; the '1'
|
||||||
// is actually implicit on a real 8088. So omit it.
|
// is actually implicit on a real 8088. So omit it.
|
||||||
if(instruction.operand() == 1) break;
|
if(instruction.second.operand() == 1) break;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
operation += ", ";
|
operation += ", ";
|
||||||
operation += to_string(instruction.source(), instruction, offset_length, immediate_length);
|
operation += to_string(instruction.second.source(), instruction.second, offset_length, immediate_length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -597,7 +597,7 @@ std::string InstructionSet::x86::to_string(
|
|||||||
//);
|
//);
|
||||||
|
|
||||||
template std::string InstructionSet::x86::to_string(
|
template std::string InstructionSet::x86::to_string(
|
||||||
Instruction<false> instruction,
|
std::pair<int, Instruction<false>> instruction,
|
||||||
Model model,
|
Model model,
|
||||||
int offset_length,
|
int offset_length,
|
||||||
int immediate_length
|
int immediate_length
|
||||||
|
@ -929,7 +929,7 @@ std::string to_string(
|
|||||||
/// If @c immediate_length is '2' or '4', truncates any printed immediate value to 2 or 4 digits if it is compatible with being that length.
|
/// If @c immediate_length is '2' or '4', truncates any printed immediate value to 2 or 4 digits if it is compatible with being that length.
|
||||||
template<bool is_32bit>
|
template<bool is_32bit>
|
||||||
std::string to_string(
|
std::string to_string(
|
||||||
Instruction<is_32bit> instruction,
|
std::pair<int, Instruction<is_32bit>> instruction,
|
||||||
Model model,
|
Model model,
|
||||||
int offset_length = 0,
|
int offset_length = 0,
|
||||||
int immediate_length = 0);
|
int immediate_length = 0);
|
||||||
|
@ -398,7 +398,7 @@ struct FailedExecution {
|
|||||||
return [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfGZippedFile:path] options:0 error:nil];
|
return [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfGZippedFile:path] options:0 error:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)toString:(const InstructionSet::x86::Instruction<false> &)instruction offsetLength:(int)offsetLength immediateLength:(int)immediateLength {
|
- (NSString *)toString:(const std::pair<int, InstructionSet::x86::Instruction<false>> &)instruction offsetLength:(int)offsetLength immediateLength:(int)immediateLength {
|
||||||
const auto operation = to_string(instruction, InstructionSet::x86::Model::i8086, offsetLength, immediateLength);
|
const auto operation = to_string(instruction, InstructionSet::x86::Model::i8086, offsetLength, immediateLength);
|
||||||
return [[NSString stringWithUTF8String:operation.c_str()] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
return [[NSString stringWithUTF8String:operation.c_str()] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||||
}
|
}
|
||||||
@ -445,12 +445,12 @@ struct FailedExecution {
|
|||||||
// The decoder doesn't preserve the original offset length, which makes no functional difference but
|
// The decoder doesn't preserve the original offset length, which makes no functional difference but
|
||||||
// does affect the way that offsets are printed in the test set.
|
// does affect the way that offsets are printed in the test set.
|
||||||
NSSet<NSString *> *decodings = [NSSet setWithObjects:
|
NSSet<NSString *> *decodings = [NSSet setWithObjects:
|
||||||
[self toString:decoded.second offsetLength:4 immediateLength:4],
|
[self toString:decoded offsetLength:4 immediateLength:4],
|
||||||
[self toString:decoded.second offsetLength:2 immediateLength:4],
|
[self toString:decoded offsetLength:2 immediateLength:4],
|
||||||
[self toString:decoded.second offsetLength:0 immediateLength:4],
|
[self toString:decoded offsetLength:0 immediateLength:4],
|
||||||
[self toString:decoded.second offsetLength:4 immediateLength:2],
|
[self toString:decoded offsetLength:4 immediateLength:2],
|
||||||
[self toString:decoded.second offsetLength:2 immediateLength:2],
|
[self toString:decoded offsetLength:2 immediateLength:2],
|
||||||
[self toString:decoded.second offsetLength:0 immediateLength:2],
|
[self toString:decoded offsetLength:0 immediateLength:2],
|
||||||
nil];
|
nil];
|
||||||
|
|
||||||
auto compare_decoding = [&](NSString *name) -> bool {
|
auto compare_decoding = [&](NSString *name) -> bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user