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:
commit
c3258551d7
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user