1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-09 00:37:27 +00:00

Merge pull request #1481 from TomHarte/x86Macros

Reduce macros in x86 decoder.
This commit is contained in:
Thomas Harte 2025-03-03 23:27:39 -05:00 committed by GitHub
commit c3258551d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 575 additions and 466 deletions

File diff suppressed because it is too large Load Diff

View File

@ -225,6 +225,148 @@ private:
sign_extend_operand_ = false;
sign_extend_displacement_ = true;
}
//
// Construction helpers.
//
/// Sets the operation and verifies that the current repetition, if any, is compatible, discarding it otherwise.
void set(const Operation operation) {
operation_ = rep_operation<model>(operation, repetition_);
};
/// Helper for those that follow...
void set(
const Operation operation,
const Source source,
const Source destination,
const DataSize operation_size
) {
set(operation);
source_ = source;
destination_ = destination;
operation_size_ = operation_size;
};
/// Covers anything which is complete as soon as the opcode is encountered.
void complete(
const Operation operation,
const Source source,
const Source destination,
const DataSize operation_size
) {
set(operation, source, destination, operation_size);
phase_ = Phase::ReadyToPost;
}
/// Handles instructions of the form rr, kk and rr, jjkk, i.e. a destination register plus an operand.
void reg_data(
const Operation operation,
const Source destination,
const DataSize operation_size
) {
set(operation, Source::Immediate, destination, operation_size);
operand_size_ = operation_size;
phase_ = Phase::DisplacementOrOperand;
}
/// Handles instructions of the form Ax, jjkk where the latter is implicitly an address.
void reg_addr(
const Operation operation,
const Source destination,
const DataSize operation_size,
const DataSize address_size
) {
set(operation, Source::DirectAddress, destination, operation_size);
displacement_size_ = address_size;
phase_ = Phase::DisplacementOrOperand;
sign_extend_displacement_ = false;
}
/// Handles instructions of the form jjkk, Ax where the former is implicitly an address.
void addr_reg(
const Operation operation,
const Source source,
const DataSize operation_size,
const DataSize address_size
) {
set(operation, source, Source::DirectAddress, operation_size);
displacement_size_ = address_size;
phase_ = Phase::DisplacementOrOperand;
sign_extend_displacement_ = false;
}
/// Covers both `mem/reg, reg` and `reg, mem/reg`.
void mem_reg_reg(
const Operation operation,
ModRegRMFormat format,
const DataSize operation_size
) {
set(operation);
phase_ = Phase::ModRegRM;
modregrm_format_ = format;
operand_size_ = DataSize::None;
operation_size_ = operation_size;
}
/// Handles JO, JNO, JB, etc — anything with only a displacement.
void displacement(
const Operation operation,
const DataSize operation_size
) {
set(operation);
phase_ = Phase::DisplacementOrOperand;
operation_size_ = displacement_size_ = operation_size;
}
/// Handles PUSH [immediate], etc — anything with only an immediate operand.
void immediate(
const Operation operation,
const DataSize operand_size
) {
set(operation);
source_ = Source::Immediate;
phase_ = Phase::DisplacementOrOperand;
operand_size_ = operand_size;
}
/// Handles far CALL and far JMP — fixed four or six byte operand operations.
void far(
const Operation operation
) {
set(operation);
phase_ = Phase::DisplacementOrOperand;
operation_size_ = operand_size_ = DataSize::Word;
destination_ = Source::Immediate;
displacement_size_ = data_size(default_address_size_);
}
/// Handles ENTER — a fixed three-byte operation.
void word_displacement_byte_operand(
const Operation operation
) {
set(operation);
phase_ = Phase::DisplacementOrOperand;
displacement_size_ = DataSize::Word;
operand_size_ = DataSize::Byte;
}
/// Sets up the operation size, oncoming phase and modregrm format for a member of the shift group (i.e. 'group 2').
void shift_group(
const int size_mask
) {
const DataSize sizes[] = {DataSize::Byte, data_size_};
phase_ = Phase::ModRegRM;
modregrm_format_ = ModRegRMFormat::MemRegROL_to_SAR;
operation_size_ = sizes[size_mask];
}
/// Constructs an instruction for 'undefined' and returns it.
std::pair<int, typename Decoder<model>::InstructionT> undefined() {
const auto result = std::make_pair(consumed_, InstructionT());
reset_parsing();
return result;
}
};
// This is a temporary measure; for reasons as-yet unknown, GCC isn't picking up the

View File

@ -33,6 +33,7 @@
#include "Numeric/RegisterSizes.hpp"
#include "Outputs/CRT/CRT.hpp"
#include "Outputs/Log.hpp"
#include "Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
#include "Storage/Disk/Track/TrackSerialiser.hpp"
@ -50,6 +51,11 @@
#include <iostream>
namespace PCCompatible {
namespace {
Log::Logger<Log::Source::PCCompatible> log;
}
using Target = Analyser::Static::PCCompatible::Target;
@ -108,7 +114,7 @@ class FloppyController {
using Command = Intel::i8272::Command;
switch(decoder_.command()) {
default:
printf("TODO: implement FDC command %d\n", uint8_t(decoder_.command()));
log.error().append("TODO: implement FDC command %d\n", uint8_t(decoder_.command()));
break;
case Command::WriteDeletedData:
@ -605,9 +611,9 @@ class IO {
switch(port) {
default:
if constexpr (std::is_same_v<IntT, uint8_t>) {
printf("Unhandled out: %02x to %04x\n", value, port);
log.error().append("Unhandled out: %02x to %04x\n", value, port);
} else {
printf("Unhandled out: %04x to %04x\n", value, port);
log.error().append("Unhandled out: %04x to %04x\n", value, port);
}
break;
@ -616,7 +622,7 @@ class IO {
// On the XT the NMI can be masked by setting bit 7 on I/O port 0xA0.
case 0x00a0:
printf("TODO: NMIs %s\n", (value & 0x80) ? "masked" : "unmasked");
log.error().append("TODO: NMIs %s\n", (value & 0x80) ? "masked" : "unmasked");
break;
case 0x0000: dma_.controller.write<0x0>(uint8_t(value)); break;
@ -689,7 +695,7 @@ class IO {
fdc_.set_digital_output(uint8_t(value));
break;
case 0x03f4:
printf("TODO: FDC write of %02x at %04x\n", value, port);
log.error().append("TODO: FDC write of %02x at %04x\n", value, port);
break;
case 0x03f5:
fdc_.write(uint8_t(value));
@ -716,7 +722,7 @@ class IO {
template <typename IntT> IntT in([[maybe_unused]] uint16_t port) {
switch(port) {
default:
printf("Unhandled in: %04x\n", port);
log.error().append("Unhandled in: %04x\n", port);
break;
case 0x0000: return dma_.controller.read<0x0>();
@ -830,7 +836,7 @@ class FlowController {
halted_ = true;
}
void wait() {
printf("WAIT ????\n");
log.error().append("WAIT ????\n");
}
void repeat_last() {

View File

@ -30,7 +30,7 @@ namespace {
// The tests themselves are not duplicated in this repository;
// provide their real path here.
constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1";
constexpr char TestSuiteHome[] = "/Users/thomasharte/Projects/8088/v1";
using Flags = InstructionSet::x86::Flags;
struct Registers {
@ -479,7 +479,7 @@ struct FailedExecution {
}
- (NSDictionary *)metadata {
NSString *path = [[NSString stringWithUTF8String:TestSuiteHome] stringByAppendingPathComponent:@"8088.json"];
NSString *path = [[NSString stringWithUTF8String:TestSuiteHome] stringByAppendingPathComponent:@"metadata.json"];
return [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfGZippedFile:path] options:0 error:nil];
}

View File

@ -48,6 +48,7 @@ enum class Source {
MSX,
NCR5380,
OpenGL,
PCCompatible,
Plus4,
PCMTrack,
SCC,
@ -122,6 +123,7 @@ constexpr const char *prefix(Source source) {
case Source::NCR5380: return "5380";
case Source::OpenGL: return "OpenGL";
case Source::Plus4: return "Plus4";
case Source::PCCompatible: return "PC";
case Source::PCMTrack: return "PCM Track";
case Source::SCSI: return "SCSI";
case Source::SCC: return "SCC";