mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Proceeds to three instructions correctly decoded. 'Wow'.
This commit is contained in:
parent
367cb1789d
commit
11b6c1d4b5
@ -61,6 +61,78 @@ namespace {
|
||||
0xb8, 0xad, 0xe8, 0xc8, 0x16, 0x4a, 0xb0, 0x9e, 0xf9, 0xbf, 0x56, 0xea, 0x4e, 0xfd, 0xe4, 0x5a,
|
||||
0x23, 0xaa, 0x2c, 0x5b, 0x2a, 0xd2, 0xf7, 0x5f, 0x18, 0x86, 0x90, 0x25, 0x64, 0xb7, 0xc3
|
||||
}];
|
||||
|
||||
// 68 instructions are expected.
|
||||
XCTAssertEqual(instructions.size(), 68);
|
||||
|
||||
// sub $0xea77,%ax
|
||||
// jb 0x00000001
|
||||
// dec %bx
|
||||
// mov $0x28,%ch
|
||||
// ret
|
||||
// lret $0x4826
|
||||
// gs insw (%dx),%es:(%di)
|
||||
// jnp 0xffffffaf
|
||||
// ret $0x4265
|
||||
// dec %si
|
||||
// out %ax,(%dx)
|
||||
// jo 0x00000037
|
||||
// xchg %ax,%sp
|
||||
// (bad)
|
||||
// aam $0x93
|
||||
// inc %bx
|
||||
// cmp $0x8e,%al
|
||||
// push $0x65
|
||||
// sbb 0x45(%bx,%si),%bh
|
||||
// adc %bh,0x3c(%bx)
|
||||
// sbb %bx,0x16(%bp,%si)
|
||||
// xor %sp,0x2c(%si)
|
||||
// out %ax,$0xc6
|
||||
// jge 0xffffffe0
|
||||
// mov $0x49,%ch
|
||||
// addr32 popa
|
||||
// mov $0xcbc0,%dx
|
||||
// adc $0x7e,%al
|
||||
// jno 0x0000000b
|
||||
// push %ax
|
||||
// js 0x0000007b
|
||||
// add (%di),%bx
|
||||
// in $0xc9,%ax
|
||||
// xchg %ax,%di
|
||||
// ret
|
||||
// fwait
|
||||
// out %al,$0xd3
|
||||
// insb (%dx),%es:(%di)
|
||||
// pop %ax
|
||||
// dec %bp
|
||||
// jbe 0xffffffcc
|
||||
// inc %sp
|
||||
// (bad)
|
||||
// lahf
|
||||
// movsw %ds:(%si),%es:(%di)
|
||||
// mov $0x12a1,%bp
|
||||
// lds (%bx,%di),%bp
|
||||
// leave
|
||||
// sahf
|
||||
// fdiv %st(3),%st
|
||||
// iret
|
||||
// xchg %ax,%dx
|
||||
// cmp %bx,-0x70(%di)
|
||||
// adc $0xb8c3,%ax
|
||||
// lods %ds:(%si),%ax
|
||||
// call 0x0000172d
|
||||
// dec %dx
|
||||
// mov $0x9e,%al
|
||||
// stc
|
||||
// mov $0xea56,%di
|
||||
// dec %si
|
||||
// std
|
||||
// in $0x5a,%al
|
||||
// and 0x5b2c(%bp,%si),%bp
|
||||
// sub %dl,%dl
|
||||
// negw 0x18(%bx)
|
||||
// xchg %dl,0x6425(%bx,%si)
|
||||
// mov $0xc3,%bh
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "x86.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
using namespace CPU::Decoder::x86;
|
||||
@ -16,7 +17,8 @@ using namespace CPU::Decoder::x86;
|
||||
Decoder::Decoder(Model) {}
|
||||
|
||||
Instruction Decoder::decode(uint8_t *source, size_t length) {
|
||||
uint8_t *const limit = source + length;
|
||||
uint8_t *const begin = source;
|
||||
uint8_t *const end = source + length;
|
||||
|
||||
#define MapPartial(value, op, lrg, fmt, phs) \
|
||||
case value: \
|
||||
@ -31,10 +33,11 @@ Instruction Decoder::decode(uint8_t *source, size_t length) {
|
||||
operation_ = Operation::op; \
|
||||
source_ = Source::src; \
|
||||
destination_ = Source::dest; \
|
||||
format_ = Format::Implied; \
|
||||
phase_ = Phase::ReadyToPost; \
|
||||
break
|
||||
|
||||
while(phase_ == Phase::Instruction && source != limit) {
|
||||
while(phase_ == Phase::Instruction && source != end) {
|
||||
// Retain the instruction byte, in case additional decoding is deferred
|
||||
// to the ModRM byte.
|
||||
instr_ = *source;
|
||||
@ -169,7 +172,7 @@ Instruction Decoder::decode(uint8_t *source, size_t length) {
|
||||
|
||||
#undef MapInstr
|
||||
|
||||
if(phase_ == Phase::ModRM && source != limit) {
|
||||
if(phase_ == Phase::ModRM && source != end) {
|
||||
const uint8_t mod = *source >> 6; // i.e. mode.
|
||||
const uint8_t reg = (*source >> 3) & 7; // i.e. register.
|
||||
const uint8_t rm = *source & 7; // i.e. register/memory.
|
||||
@ -234,12 +237,51 @@ Instruction Decoder::decode(uint8_t *source, size_t length) {
|
||||
++consumed_;
|
||||
}
|
||||
|
||||
if(phase_ == Phase::AwaitingOperands && source != limit) {
|
||||
if(phase_ == Phase::AwaitingOperands && source != end) {
|
||||
// TODO: calculate number of expected operands.
|
||||
const int required_bytes = large_operand_ ? 2 : 1;
|
||||
|
||||
const int outstanding_bytes = required_bytes - operand_bytes_;
|
||||
const int bytes_to_consume = std::min(int(end - source), outstanding_bytes);
|
||||
source += bytes_to_consume;
|
||||
consumed_ += bytes_to_consume;
|
||||
operand_bytes_ += bytes_to_consume;
|
||||
if(bytes_to_consume == outstanding_bytes) {
|
||||
phase_ = Phase::ReadyToPost;
|
||||
} else {
|
||||
// Provide a genuine measure of further bytes required.
|
||||
return Instruction(-(outstanding_bytes - bytes_to_consume));
|
||||
}
|
||||
}
|
||||
|
||||
if(phase_ == Phase::ReadyToPost) {
|
||||
// TODO: construct actual Instruction.
|
||||
Instruction result;
|
||||
switch(format_) {
|
||||
case Format::Ac_Data:
|
||||
if(large_operand_) {
|
||||
result = Instruction(operation_, Size::Word, Source::AX, Source::Immediate, consumed_);
|
||||
} else {
|
||||
result = Instruction(operation_, Size::Byte, Source::AL, Source::Immediate, consumed_);
|
||||
}
|
||||
break;
|
||||
|
||||
case Format::Disp:
|
||||
result = Instruction(operation_, Size::Byte, Source::Immediate, Source::None, consumed_);
|
||||
break;
|
||||
|
||||
case Format::Implied:
|
||||
result = Instruction(operation_, large_operand_ ? Size::Word : Size::Byte, source_, destination_, consumed_);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Reset parser.
|
||||
consumed_ = operand_bytes_ = 0;
|
||||
lock_ = add_offset_ = large_offset_ = false;
|
||||
phase_ = Phase::Instruction;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return Instruction();
|
||||
|
@ -76,18 +76,23 @@ enum class Source: uint8_t {
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
const Operation operation = Operation::Invalid;
|
||||
const Size operand_size = Size::Byte;
|
||||
Operation operation = Operation::Invalid;
|
||||
Size operand_size = Size::Byte;
|
||||
|
||||
const Source source = Source::AL;
|
||||
const Source destination = Source::AL;
|
||||
Source source = Source::AL;
|
||||
Source destination = Source::AL;
|
||||
|
||||
int size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
Instruction() {}
|
||||
Instruction(int size) : size_(size) {}
|
||||
Instruction(Operation operation, Size operand_size, Source source, Source destination, int size) :
|
||||
operation(operation), operand_size(operand_size), source(source), destination(destination), size_(size) {}
|
||||
|
||||
private:
|
||||
int size_ = 0;
|
||||
int size_ = -1;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -117,6 +122,7 @@ struct Decoder {
|
||||
} phase_ = Phase::Instruction;
|
||||
|
||||
enum class Format: uint8_t {
|
||||
Implied,
|
||||
MemReg_Reg,
|
||||
Reg_MemReg,
|
||||
Ac_Data,
|
||||
@ -134,8 +140,8 @@ struct Decoder {
|
||||
None, RepE, RepNE
|
||||
} repetition_ = Repetition::None;
|
||||
|
||||
|
||||
int consumed_ = 0;
|
||||
int operand_bytes_ = 0;
|
||||
Operation operation_ = Operation::Invalid;
|
||||
bool large_operand_ = false;
|
||||
Source source_ = Source::None;
|
||||
|
Loading…
Reference in New Issue
Block a user