mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Does the easier part of the easier half of 8086 decoding.
This commit is contained in:
parent
a41be61f99
commit
dc9d370952
@ -183,6 +183,8 @@
|
||||
4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */; };
|
||||
4B3BA0D11D318B44005DD7A7 /* TestMachine6502.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CD1D318B44005DD7A7 /* TestMachine6502.mm */; };
|
||||
4B3BF5B01F146265005B6C36 /* CSW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BF5AE1F146264005B6C36 /* CSW.cpp */; };
|
||||
4B3F76AE25A0196100178AEC /* x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F76AD25A0196100178AEC /* x86.cpp */; };
|
||||
4B3F76AF25A0196100178AEC /* x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F76AD25A0196100178AEC /* x86.cpp */; };
|
||||
4B3FCC40201EC24200960631 /* MultiMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FCC3F201EC24200960631 /* MultiMachine.cpp */; };
|
||||
4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */; };
|
||||
4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */; };
|
||||
@ -1077,6 +1079,8 @@
|
||||
4B3BF5AE1F146264005B6C36 /* CSW.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSW.cpp; sourceTree = "<group>"; };
|
||||
4B3BF5AF1F146264005B6C36 /* CSW.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CSW.hpp; sourceTree = "<group>"; };
|
||||
4B3F769E259FCE0F00178AEC /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
4B3F76AC25A0196100178AEC /* x86.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = x86.hpp; sourceTree = "<group>"; };
|
||||
4B3F76AD25A0196100178AEC /* x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x86.cpp; sourceTree = "<group>"; };
|
||||
4B3FCC3E201EC24200960631 /* MultiMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiMachine.hpp; sourceTree = "<group>"; };
|
||||
4B3FCC3F201EC24200960631 /* MultiMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiMachine.cpp; sourceTree = "<group>"; };
|
||||
4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPM.cpp; path = Parsers/CPM.cpp; sourceTree = "<group>"; };
|
||||
@ -2324,6 +2328,15 @@
|
||||
path = Bridges;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B3F76AB25A0196100178AEC /* x86 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B3F76AC25A0196100178AEC /* x86.hpp */,
|
||||
4B3F76AD25A0196100178AEC /* x86.cpp */,
|
||||
);
|
||||
path = x86;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B3FCC3D201EC24200960631 /* MultiMachine */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3892,6 +3905,7 @@
|
||||
children = (
|
||||
4B3F769E259FCE0F00178AEC /* README.md */,
|
||||
4BDDBBD4259D757800CEFF58 /* PowerPC */,
|
||||
4B3F76AB25A0196100178AEC /* x86 */,
|
||||
);
|
||||
path = Decoders;
|
||||
sourceTree = "<group>";
|
||||
@ -4666,6 +4680,7 @@
|
||||
4B0F94FF208C1A1600FE41D9 /* NIB.cpp in Sources */,
|
||||
4B0E04EB1FC9E78800F43484 /* CAS.cpp in Sources */,
|
||||
4BB0A65D2045009000FB3688 /* ColecoVision.cpp in Sources */,
|
||||
4B3F76AF25A0196100178AEC /* x86.cpp in Sources */,
|
||||
4BB0A65C2044FD3000FB3688 /* SN76489.cpp in Sources */,
|
||||
4B595FAE2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */,
|
||||
4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */,
|
||||
@ -4738,6 +4753,7 @@
|
||||
4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */,
|
||||
4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */,
|
||||
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */,
|
||||
4B3F76AE25A0196100178AEC /* x86.cpp in Sources */,
|
||||
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
|
||||
4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */,
|
||||
4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */,
|
||||
|
126
Processors/Decoders/x86/x86.cpp
Normal file
126
Processors/Decoders/x86/x86.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// x86.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 1/1/21.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "x86.hpp"
|
||||
|
||||
using namespace CPU::Decoder::x86;
|
||||
|
||||
Instruction Decoder::decode(uint8_t *source, size_t length) {
|
||||
uint8_t *const limit = source + length;
|
||||
|
||||
#define MapPartial(value, op, sz, fmt, phs) \
|
||||
case value: \
|
||||
operation_ = Operation::op; \
|
||||
operand_size_ = Size::sz; \
|
||||
format_ = Format::fmt; \
|
||||
phase_ = Phase::phs; \
|
||||
break;
|
||||
|
||||
#define MapComplete(value, op, sz, src, dest) \
|
||||
case value: \
|
||||
operation_ = Operation::op; \
|
||||
operand_size_ = Size::sz; \
|
||||
source_ = Source::src; \
|
||||
destination_ = Source::dest; \
|
||||
phase_ = Phase::ReadyToPost; \
|
||||
break;
|
||||
|
||||
while(phase_ == Phase::Instruction && source != limit) {
|
||||
switch(*source) {
|
||||
#define PartialBlock(start, operation) \
|
||||
MapPartial(start + 0x00, operation, Byte, MemReg_Reg, ModRM); \
|
||||
MapPartial(start + 0x01, operation, Word, MemReg_Reg, ModRM); \
|
||||
MapPartial(start + 0x02, operation, Byte, Reg_MemReg, ModRM); \
|
||||
MapPartial(start + 0x03, operation, Word, Reg_MemReg, ModRM); \
|
||||
MapPartial(start + 0x04, operation, Byte, Ac_Data, AwaitingOperands); \
|
||||
MapPartial(start + 0x05, operation, Word, Ac_Data, AwaitingOperands);
|
||||
|
||||
PartialBlock(0x00, ADD);
|
||||
MapComplete(0x06, PUSH, Word, ES, None);
|
||||
MapComplete(0x07, POP, Word, ES, None);
|
||||
|
||||
PartialBlock(0x08, OR);
|
||||
MapComplete(0x0e, PUSH, Word, CS, None);
|
||||
/* 0x0f: not used. */
|
||||
|
||||
PartialBlock(0x10, ADC);
|
||||
MapComplete(0x16, PUSH, Word, SS, None);
|
||||
MapComplete(0x17, POP, Word, SS, None);
|
||||
|
||||
PartialBlock(0x18, SBB);
|
||||
MapComplete(0x1e, PUSH, Word, DS, None);
|
||||
MapComplete(0x1f, POP, Word, DS, None);
|
||||
|
||||
PartialBlock(0x20, AND);
|
||||
case 0x26: segment_override_ = Source::ES; break;
|
||||
MapComplete(0x27, DAA, Implied, None, None);
|
||||
|
||||
PartialBlock(0x28, SUB);
|
||||
case 0x2e: segment_override_ = Source::CS; break;
|
||||
MapComplete(0x2f, DAS, Implied, None, None);
|
||||
|
||||
PartialBlock(0x30, XOR);
|
||||
case 0x36: segment_override_ = Source::SS; break;
|
||||
MapComplete(0x37, AAA, Implied, None, None);
|
||||
|
||||
PartialBlock(0x38, CMP);
|
||||
case 0x3e: segment_override_ = Source::DS; break;
|
||||
MapComplete(0x3f, AAS, Implied, None, None);
|
||||
|
||||
#undef PartialBlock
|
||||
|
||||
#define RegisterBlock(start, operation) \
|
||||
MapComplete(start + 0x00, operation, Word, AX, AX); \
|
||||
MapComplete(start + 0x01, operation, Word, CX, CX); \
|
||||
MapComplete(start + 0x02, operation, Word, DX, DX); \
|
||||
MapComplete(start + 0x03, operation, Word, BX, BX); \
|
||||
MapComplete(start + 0x04, operation, Word, SP, SP); \
|
||||
MapComplete(start + 0x05, operation, Word, BP, BP); \
|
||||
MapComplete(start + 0x06, operation, Word, SI, SI); \
|
||||
MapComplete(start + 0x07, operation, Word, DI, DI); \
|
||||
|
||||
RegisterBlock(0x40, INC);
|
||||
RegisterBlock(0x48, DEC);
|
||||
RegisterBlock(0x50, PUSH);
|
||||
RegisterBlock(0x58, POP);
|
||||
|
||||
#undef RegisterBlock
|
||||
|
||||
/* 0x60–0x6f: not used. */
|
||||
|
||||
MapPartial(0x70, JO, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x71, JNO, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x72, JB, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x73, JNB, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x74, JE, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x75, JNE, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x76, JBE, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x77, JNBE, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x78, JS, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x79, JNS, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7a, JP, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7b, JNP, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7c, JL, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7d, JNL, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7e, JLE, Byte, Disp, AwaitingOperands);
|
||||
MapPartial(0x7f, JNLE, Byte, Disp, AwaitingOperands);
|
||||
|
||||
}
|
||||
++source;
|
||||
++consumed_;
|
||||
}
|
||||
|
||||
#undef MapInstr
|
||||
|
||||
|
||||
if(phase_ == Phase::ReadyToPost) {
|
||||
// TODO: construct actual Instruction.
|
||||
}
|
||||
|
||||
return Instruction();
|
||||
}
|
127
Processors/Decoders/x86/x86.hpp
Normal file
127
Processors/Decoders/x86/x86.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// x86.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 1/1/21.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef x86_hpp
|
||||
#define x86_hpp
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace CPU {
|
||||
namespace Decoder {
|
||||
namespace x86 {
|
||||
|
||||
enum class Model {
|
||||
i8086,
|
||||
};
|
||||
|
||||
enum class Operation: uint8_t {
|
||||
Invalid,
|
||||
|
||||
AAA, AAD, AAM, AAS, ADC, ADD, AND, CALL, CBW, CLC, CLD, CLI, CMC,
|
||||
CMP, CMPS, CWD, DAA, DAS, DEC, DIV, ESC, HLT, IDIV, IMUL, IN,
|
||||
INC, INT, INTO, IRET,
|
||||
JO, JNO,
|
||||
JB, JNB,
|
||||
JE, JNE,
|
||||
JBE, JNBE,
|
||||
JS, JNS,
|
||||
JP, JNP,
|
||||
JL, JNL,
|
||||
JLE, JNLE,
|
||||
JMP, JCXZ,
|
||||
LAHF, LDS, LEA,
|
||||
LODS, LOOPE, LOOPNE, MOV, MOVS, MUL, NEG, NOP, NOT, OR, OUT,
|
||||
POP, POPF, PUSH, PUSHF, RCL, RCR, REP, RET, ROL, ROR, SAHF,
|
||||
SAR, SBB, SCAS, SHL, SHR, STC, STD, STI, STOS, SUB, TEST,
|
||||
WAIT, XCHG, XLAT, XOR
|
||||
};
|
||||
|
||||
enum class Size: uint8_t {
|
||||
Implied = 0,
|
||||
Byte = 1,
|
||||
Word = 2,
|
||||
};
|
||||
|
||||
enum class Source: uint8_t {
|
||||
None,
|
||||
|
||||
AL, AH, AX,
|
||||
BL, BH, BX,
|
||||
CL, CH, CX,
|
||||
DL, DH, DX,
|
||||
|
||||
CS, DS, ES, SS,
|
||||
SI, DI,
|
||||
BP, SP,
|
||||
|
||||
Memory, Immediate
|
||||
};
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
const Operation operation = Operation::Invalid;
|
||||
const Size operand_size = Size::Byte;
|
||||
|
||||
const Source source = Source::AL;
|
||||
const Source destination = Source::AL;
|
||||
|
||||
int size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
private:
|
||||
int size_ = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
Implements Intel x86 instruction decoding.
|
||||
|
||||
This is an experimental implementation; it has not yet undergone significant testing.
|
||||
*/
|
||||
struct Decoder {
|
||||
public:
|
||||
Decoder(Model model);
|
||||
|
||||
/*!
|
||||
@returns an @c Instruction with a positive size to indicate successful decoding; a
|
||||
negative size specifies the number of further bytes required fully to decode, and
|
||||
a zero size indicates that further bytes are required but the decoder does not yet
|
||||
know exactly how many.
|
||||
*/
|
||||
Instruction decode(uint8_t *source, size_t length);
|
||||
|
||||
private:
|
||||
enum class Phase {
|
||||
Instruction,
|
||||
ModRM,
|
||||
AwaitingOperands,
|
||||
ReadyToPost
|
||||
} phase_ = Phase::Instruction;
|
||||
|
||||
enum class Format: uint8_t {
|
||||
MemReg_Reg,
|
||||
Reg_MemReg,
|
||||
Ac_Data,
|
||||
MemReg_Data,
|
||||
Disp
|
||||
} format_ = Format::MemReg_Reg;
|
||||
|
||||
int consumed_ = 0;
|
||||
Operation operation_ = Operation::Invalid;
|
||||
Size operand_size_ = Size::Implied;
|
||||
Source source_ = Source::None;
|
||||
Source destination_ = Source::None;
|
||||
Source segment_override_ = Source::None;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* x86_hpp */
|
Loading…
x
Reference in New Issue
Block a user