1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-17 13:29:02 +00:00
CLK/Processors/Decoders/x86/x86.cpp

127 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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
/* 0x600x6f: 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();
}