1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-18 16:30:29 +00:00

Agree that JZ/JNZ are clearer (for me) of the synonyms.

This commit is contained in:
Thomas Harte 2023-09-19 13:38:08 -04:00
parent 2d928199d6
commit e5dfc882cb
5 changed files with 53 additions and 30 deletions

View File

@ -261,8 +261,8 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
case 0x71: Displacement(JNO, DataSize::Byte); break; case 0x71: Displacement(JNO, DataSize::Byte); break;
case 0x72: Displacement(JB, DataSize::Byte); break; case 0x72: Displacement(JB, DataSize::Byte); break;
case 0x73: Displacement(JNB, DataSize::Byte); break; case 0x73: Displacement(JNB, DataSize::Byte); break;
case 0x74: Displacement(JE, DataSize::Byte); break; case 0x74: Displacement(JZ, DataSize::Byte); break;
case 0x75: Displacement(JNE, DataSize::Byte); break; case 0x75: Displacement(JNZ, DataSize::Byte); break;
case 0x76: Displacement(JBE, DataSize::Byte); break; case 0x76: Displacement(JBE, DataSize::Byte); break;
case 0x77: Displacement(JNBE, DataSize::Byte); break; case 0x77: Displacement(JNBE, DataSize::Byte); break;
case 0x78: Displacement(JS, DataSize::Byte); break; case 0x78: Displacement(JS, DataSize::Byte); break;
@ -497,8 +497,8 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
case 0x71: RequiresMin(i80386); Displacement(JNO, data_size_); break; case 0x71: RequiresMin(i80386); Displacement(JNO, data_size_); break;
case 0x72: RequiresMin(i80386); Displacement(JB, data_size_); break; case 0x72: RequiresMin(i80386); Displacement(JB, data_size_); break;
case 0x73: RequiresMin(i80386); Displacement(JNB, data_size_); break; case 0x73: RequiresMin(i80386); Displacement(JNB, data_size_); break;
case 0x74: RequiresMin(i80386); Displacement(JE, data_size_); break; case 0x74: RequiresMin(i80386); Displacement(JZ, data_size_); break;
case 0x75: RequiresMin(i80386); Displacement(JNE, data_size_); break; case 0x75: RequiresMin(i80386); Displacement(JNZ, data_size_); break;
case 0x76: RequiresMin(i80386); Displacement(JBE, data_size_); break; case 0x76: RequiresMin(i80386); Displacement(JBE, data_size_); break;
case 0x77: RequiresMin(i80386); Displacement(JNBE, data_size_); break; case 0x77: RequiresMin(i80386); Displacement(JNBE, data_size_); break;
case 0x78: RequiresMin(i80386); Displacement(JS, data_size_); break; case 0x78: RequiresMin(i80386); Displacement(JS, data_size_); break;

View File

@ -45,8 +45,8 @@ std::string InstructionSet::x86::to_string(Operation operation, DataSize size) {
case Operation::JNO: return "jno"; case Operation::JNO: return "jno";
case Operation::JB: return "jb"; case Operation::JB: return "jb";
case Operation::JNB: return "jnb"; case Operation::JNB: return "jnb";
case Operation::JE: return "jo"; case Operation::JZ: return "jz";
case Operation::JNE: return "jne"; case Operation::JNZ: return "jnz";
case Operation::JBE: return "jbe"; case Operation::JBE: return "jbe";
case Operation::JNBE: return "jnbe"; case Operation::JNBE: return "jnbe";
case Operation::JS: return "js"; case Operation::JS: return "js";

View File

@ -87,7 +87,7 @@ enum class Operation: uint8_t {
OUT, OUT,
// Various jumps; see the displacement to calculate targets. // Various jumps; see the displacement to calculate targets.
JO, JNO, JB, JNB, JE, JNE, JBE, JNBE, JO, JNO, JB, JNB, JZ, JNZ, JBE, JNBE,
JS, JNS, JP, JNP, JL, JNL, JLE, JNLE, JS, JNS, JP, JNP, JL, JNL, JLE, JNLE,
/// Near call. /// Near call.
@ -340,18 +340,26 @@ enum class Operation: uint8_t {
MOVtoTr, MOVfromTr, MOVtoTr, MOVfromTr,
}; };
constexpr int num_operands(Operation operation) { constexpr bool has_displacement(Operation operation) {
switch(operation) { switch(operation) {
default: return 2; default: return false;
case Operation::JO: case Operation::JNO: case Operation::JO: case Operation::JNO:
case Operation::JB: case Operation::JNB: case Operation::JB: case Operation::JNB:
case Operation::JE: case Operation::JNE: case Operation::JZ: case Operation::JNZ:
case Operation::JBE: case Operation::JNBE: case Operation::JBE: case Operation::JNBE:
case Operation::JS: case Operation::JNS: case Operation::JS: case Operation::JNS:
case Operation::JP: case Operation::JNP: case Operation::JP: case Operation::JNP:
case Operation::JL: case Operation::JNL: case Operation::JL: case Operation::JNL:
case Operation::JLE: case Operation::JNLE: case Operation::JLE: case Operation::JNLE:
return true;
}
}
constexpr int num_operands(Operation operation) {
switch(operation) {
default: return 2;
case Operation::INC: case Operation::DEC: case Operation::INC: case Operation::DEC:
case Operation::POP: case Operation::PUSH: case Operation::POP: case Operation::PUSH:
case Operation::MUL: case Operation::MUL:
@ -360,6 +368,16 @@ constexpr int num_operands(Operation operation) {
case Operation::ESC: case Operation::ESC:
return 1; return 1;
// Pedantically, these have an displacement rather than an operand.
case Operation::JO: case Operation::JNO:
case Operation::JB: case Operation::JNB:
case Operation::JZ: case Operation::JNZ:
case Operation::JBE: case Operation::JNBE:
case Operation::JS: case Operation::JNS:
case Operation::JP: case Operation::JNP:
case Operation::JL: case Operation::JNL:
case Operation::JLE: case Operation::JNLE:
// Genuine zero-operand instructions:
case Operation::CMPS: case Operation::LODS: case Operation::CMPS: case Operation::LODS:
case Operation::MOVS: case Operation::SCAS: case Operation::MOVS: case Operation::SCAS:
case Operation::STOS: case Operation::STOS:

View File

@ -104,7 +104,19 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"
operation += to_string(decoded.second.operation, decoded.second.operation_size()); operation += to_string(decoded.second.operation, decoded.second.operation_size());
auto to_string = [] (InstructionSet::x86::DataPointer pointer, const auto &instruction) -> std::string { auto to_hex = [] (int value, int digits) -> std::string {
auto stream = std::stringstream();
stream << std::setfill('0') << std::uppercase << std::hex << std::setw(digits);
switch(digits) {
case 2: stream << +uint8_t(value); break;
case 4: stream << +uint16_t(value); break;
default: stream << value; break;
}
stream << 'h';
return stream.str();
};
auto to_string = [&to_hex] (InstructionSet::x86::DataPointer pointer, const auto &instruction) -> std::string {
std::string operand; std::string operand;
using Source = InstructionSet::x86::Source; using Source = InstructionSet::x86::Source;
@ -113,17 +125,11 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"
// to_string handles all direct register names correctly. // to_string handles all direct register names correctly.
default: return InstructionSet::x86::to_string(source, instruction.operation_size()); default: return InstructionSet::x86::to_string(source, instruction.operation_size());
case Source::Immediate: { case Source::Immediate:
auto stream = std::stringstream(); return to_hex(
stream << std::setfill('0') << std::uppercase << std::hex; instruction.operand(),
if(instruction.operation_size() == InstructionSet::x86::DataSize::Byte) { instruction.operation_size() == InstructionSet::x86::DataSize::Byte ? 2 : 4
stream << std::setw(2) << uint8_t(instruction.operand()); );
} else {
stream << std::setw(4) << instruction.operand();
}
stream << 'h';
return stream.str();
}
case Source::Indirect: case Source::Indirect:
return (std::stringstream() << return (std::stringstream() <<
@ -139,18 +145,17 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"
}; };
const int operands = num_operands(decoded.second.operation); const int operands = num_operands(decoded.second.operation);
const bool displacement = has_displacement(decoded.second.operation);
operation += " ";
if(operands > 1) { if(operands > 1) {
operation += " ";
operation += to_string(decoded.second.destination(), decoded.second); operation += to_string(decoded.second.destination(), decoded.second);
operation += ","; operation += ", ";
} }
if(operands > 0) { if(operands > 0) {
operation += " ";
operation += to_string(decoded.second.source(), decoded.second); operation += to_string(decoded.second.source(), decoded.second);
} }
if(!operands) { if(displacement) {
// These tests always leave a space after the operation. operation += to_hex(decoded.second.displacement(), 2);
operation += " ";
} }
const NSString *objcOperation = [NSString stringWithUTF8String:operation.c_str()]; const NSString *objcOperation = [NSString stringWithUTF8String:operation.c_str()];

View File

@ -533,11 +533,11 @@ decode(const std::initializer_list<uint8_t> &stream, bool set_32_bit = false) {
// cmp ecx,DWORD PTR [ebp+0x2c87445f] // cmp ecx,DWORD PTR [ebp+0x2c87445f]
// jecxz 0x00000084 (from 0x82) // jecxz 0x00000084 (from 0x82)
// sahf // sahf
// je 0x000000f3 (from 0x85) // jz 0x000000f3 (from 0x85)
test(instructions[52], DataSize::DWord, Operation::CMP, ScaleIndexBase(Source::eBP), Source::eCX, 0, 0x2c87445f); test(instructions[52], DataSize::DWord, Operation::CMP, ScaleIndexBase(Source::eBP), Source::eCX, 0, 0x2c87445f);
test(instructions[53], Operation::JPCX, 0, 0x02); test(instructions[53], Operation::JPCX, 0, 0x02);
test(instructions[54], Operation::SAHF); test(instructions[54], Operation::SAHF);
test(instructions[55], Operation::JE, 0, 0x6e); test(instructions[55], Operation::JZ, 0, 0x6e);
// sbb ecx,DWORD PTR [edi+0x433c54d] // sbb ecx,DWORD PTR [edi+0x433c54d]
// lahf // lahf