Started implementing the 8086 simulation

This commit is contained in:
Abdelrahman Said 2023-03-29 01:28:37 +01:00
parent 732aa2803f
commit 96d1381303
20 changed files with 832 additions and 0 deletions

8
8086_sim/Makefile Normal file
View File

@ -0,0 +1,8 @@
CC=clang++
CFLAGS=-g -O0 -Wall -Wextra
LIBS=-Wl,-rpath,./lib -L./lib -lsim86
SRC=*.cpp
OUT=sim86
all:
$(CC) $(CFLAGS) $(LIBS) $(SRC) -o $(OUT)

View File

@ -0,0 +1,46 @@
#ifndef ALIASES_H
#define ALIASES_H
#include <stdint.h>
#ifndef u8
#define u8 uint8_t
#endif // !u8
#ifndef u16
#define u16 uint16_t
#endif // !u16
#ifndef u32
#define u32 uint32_t
#endif // !u32
#ifndef u64
#define u64 uint64_t
#endif // !u64
#ifndef i8
#define i8 int8_t
#endif // !i8
#ifndef i16
#define i16 int16_t
#endif // !i16
#ifndef i32
#define i32 int32_t
#endif // !i32
#ifndef i64
#define i64 int64_t
#endif // !i64
#ifndef f32
#define f32 float
#endif // !f32
#ifndef f64
#define f64 double
#endif // !f64
#endif // !ALIASES_H

View File

@ -0,0 +1,11 @@
#ifndef REG_ACCESS_H
#define REG_ACCESS_H
#include "aliases.h"
#include "sim86_instruction.h"
void set_register(register_access reg, u16 new_value);
u16 get_register(register_access reg);
const char *get_register_name(register_access reg);
#endif // !REG_ACCESS_H

54
8086_sim/include/sim86.h Normal file
View File

@ -0,0 +1,54 @@
/* ========================================================================
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Please see https://computerenhance.com for more information
======================================================================== */
#ifndef SIM86_H
#define SIM86_H
#ifndef u8
typedef char unsigned u8;
#endif // !u8
#ifndef u16
typedef short unsigned u16;
#endif // !u16
#ifndef u32
typedef int unsigned u32;
#endif // !u32
#ifndef u64
typedef long long unsigned u64;
#endif // u64
#ifndef s8
typedef char s8;
#endif // !s8
#ifndef s16
typedef short s16;
#endif // !s16
#ifndef s32
typedef int s32;
#endif // !s32
#ifndef s64
typedef long long s64;
#endif // !s64
typedef s32 b32;
#define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0]))
static u32 const SIM86_VERSION = 3;
#endif // !SIM86_H

View File

@ -0,0 +1,92 @@
/* ========================================================================
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Please see https://computerenhance.com for more information
======================================================================== */
#ifndef SIM86_INST_H
#define SIM86_INST_H
#include "sim86.h"
enum operation_type : u32 {
Op_None,
#define INST(Mnemonic, ...) Op_##Mnemonic,
#define INSTALT(...)
#include "sim86_instruction_table.inl"
Op_Count,
};
enum instruction_flag : u32 {
Inst_Lock = 0x1,
Inst_Rep = 0x2,
Inst_Segment = 0x4,
Inst_Wide = 0x8,
Inst_Far = 0x10,
};
struct register_access {
u32 Index; // Index in the register table
u32 Offset; // High vs Low bits
u32 Count; // How many bytes are accessed
};
struct effective_address_term {
register_access Register;
s32 Scale;
};
enum effective_address_flag : u32 {
Address_ExplicitSegment = 0x1,
};
struct effective_address_expression {
effective_address_term Terms[2];
u32 ExplicitSegment;
s32 Displacement;
u32 Flags;
};
enum immediate_flag : u32 {
Immediate_RelativeJumpDisplacement = 0x1,
};
struct immediate {
s32 Value;
u32 Flags;
};
enum operand_type : u32 {
Operand_None,
Operand_Register,
Operand_Memory,
Operand_Immediate,
};
struct instruction_operand {
operand_type Type;
union {
effective_address_expression Address;
register_access Register;
immediate Immediate;
};
};
struct instruction {
u32 Address;
u32 Size;
operation_type Op;
u32 Flags;
instruction_operand Operands[2];
u32 SegmentOverride;
};
#endif // !SIM86_INST_H

View File

@ -0,0 +1,65 @@
/* ========================================================================
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Please see https://computerenhance.com for more information
======================================================================== */
#include "sim86.h"
#include "sim86_instruction.h"
enum instruction_bits_usage : u8 {
Bits_End, // NOTE(casey): The 0 value, indicating the end of the instruction
// encoding array
Bits_Literal, // NOTE(casey): These are opcode bits that identify instructions
// NOTE(casey): These bits correspond directly to the 8086 instruction manual
Bits_D,
Bits_S,
Bits_W,
Bits_V,
Bits_Z,
Bits_MOD,
Bits_REG,
Bits_RM,
Bits_SR,
Bits_Disp,
Bits_Data,
Bits_DispAlwaysW, // NOTE(casey): Tag for instructions where the displacement
// is always 16 bits
Bits_WMakesDataW, // NOTE(casey): Tag for instructions where SW=01 makes the
// data field become 16 bits
Bits_RMRegAlwaysW, // NOTE(casey): Tag for instructions where the register
// encoded in RM is always 16-bit width
Bits_RelJMPDisp, // NOTE(casey): Tag for instructions that require address
// adjustment to go through NASM properly
Bits_Far, // NOTE(casey): Tag for instructions that require a "far" keyword in
// their ASM to select the right opcode
Bits_Count,
};
struct instruction_bits {
instruction_bits_usage Usage;
u8 BitCount;
u8 Shift;
u8 Value;
};
struct instruction_encoding {
operation_type Op;
instruction_bits Bits[16];
};
struct instruction_table {
instruction_encoding *Encodings;
u32 EncodingCount;
u32 MaxInstructionByteCount;
};

View File

@ -0,0 +1,250 @@
/* ========================================================================
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Please see https://computerenhance.com for more information
======================================================================== */
/*
NOTE(casey): This instruction table is a direct translation of table 4-12 in the Intel 8086 manual.
The macros are designed to allow direct transcription, without changing the order or manner
of specification in the table in any way. Additional "implicit" versions of the macros are provided
so that hard-coded fields can be supplied uniformly.
The table is also designed to allow you to include it multiple times to "pull out" other things
from the table, such as opcode mnemonics as strings or enums, etc.
*/
#ifndef INST
#define INST(Mnemonic, Encoding, ...) {Op_##Mnemonic, Encoding, __VA_ARGS__},
#endif
#ifndef INSTALT
#define INSTALT INST
#endif
#define B(Bits) {Bits_Literal, sizeof(#Bits)-1, 0, 0b##Bits}
#define D {Bits_D, 1}
#define S {Bits_S, 1}
#define W {Bits_W, 1}
#define V {Bits_V, 1}
#define Z {Bits_Z, 1}
#define XXX {Bits_Data, 3, 0}
#define YYY {Bits_Data, 3, 3}
#define RM {Bits_RM, 3}
#define MOD {Bits_MOD, 2}
#define REG {Bits_REG, 3}
#define SR {Bits_SR, 2}
#define ImpW(Value) {Bits_W, 0, 0, Value}
#define ImpREG(Value) {Bits_REG, 0, 0, Value}
#define ImpMOD(Value) {Bits_MOD, 0, 0, Value}
#define ImpRM(Value) {Bits_RM, 0, 0, Value}
#define ImpD(Value) {Bits_D, 0, 0, Value}
#define ImpS(Value) {Bits_S, 0, 0, Value}
#define DISP {Bits_Disp, 0, 0, 0}
#define ADDR {Bits_Disp, 0, 0, 0}, {Bits_DispAlwaysW, 0, 0, 1}
#define DATA {Bits_Data, 0, 0, 0}
#define DATA_IF_W {Bits_WMakesDataW, 0, 0, 1}
#define Flags(F) {F, 0, 0, 1}
INST(mov, {B(100010), D, W, MOD, REG, RM})
INSTALT(mov, {B(1100011), W, MOD, B(000), RM, DATA, DATA_IF_W, ImpD(0)})
INSTALT(mov, {B(1011), W, REG, DATA, DATA_IF_W, ImpD(1)})
INSTALT(mov, {B(1010000), W, ADDR, ImpREG(0), ImpMOD(0), ImpRM(0b110), ImpD(1)})
INSTALT(mov, {B(1010001), W, ADDR, ImpREG(0), ImpMOD(0), ImpRM(0b110), ImpD(0)})
INSTALT(mov, {B(100011), D, B(0), MOD, B(0), SR, RM, ImpW(1)}) // NOTE(casey): This collapses 2 entries in the 8086 table by adding an explicit D bit
INST(push, {B(11111111), MOD, B(110), RM, ImpW(1)})
INSTALT(push, {B(01010), REG, ImpW(1)})
INSTALT(push, {B(000), SR, B(110), ImpW(1)})
INST(pop, {B(10001111), MOD, B(000), RM, ImpW(1)})
INSTALT(pop, {B(01011), REG, ImpW(1)})
INSTALT(pop, {B(000), SR, B(111), ImpW(1)})
INST(xchg, {B(1000011), W, MOD, REG, RM, ImpD(1)})
INSTALT(xchg, {B(10010), REG, ImpMOD(0b11), ImpW(1), ImpRM(0)})
INST(in, {B(1110010), W, DATA, ImpREG(0), ImpD(1)})
INSTALT(in, {B(1110110), W, ImpREG(0), ImpD(1), ImpMOD(0b11), ImpRM(2), Flags(Bits_RMRegAlwaysW)})
INST(out, {B(1110011), W, DATA, ImpREG(0), ImpD(0)})
INSTALT(out, {B(1110111), W, ImpREG(0), ImpD(0), ImpMOD(0b11), ImpRM(2), Flags(Bits_RMRegAlwaysW)})
INST(xlat, {B(11010111)})
INST(lea, {B(10001101), MOD, REG, RM, ImpD(1), ImpW(1)})
INST(lds, {B(11000101), MOD, REG, RM, ImpD(1), ImpW(1)})
INST(les, {B(11000100), MOD, REG, RM, ImpD(1), ImpW(1)})
INST(lahf, {B(10011111)})
INST(sahf, {B(10011110)})
INST(pushf, {B(10011100)})
INST(popf, {B(10011101)})
INST(add, {B(000000), D, W, MOD, REG, RM})
INSTALT(add, {B(100000), S, W, MOD, B(000), RM, DATA, DATA_IF_W})
INSTALT(add, {B(0000010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(adc, {B(000100), D, W, MOD, REG, RM})
INSTALT(adc, {B(100000), S, W, MOD, B(010), RM, DATA, DATA_IF_W})
INSTALT(adc, {B(0001010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(inc, {B(1111111), W, MOD, B(000), RM})
INSTALT(inc, {B(01000), REG, ImpW(1)})
INST(aaa, {B(00110111)})
INST(daa, {B(00100111)})
INST(sub, {B(001010), D, W, MOD, REG, RM})
INSTALT(sub, {B(100000), S, W, MOD, B(101), RM, DATA, DATA_IF_W})
INSTALT(sub, {B(0010110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(sbb, {B(000110), D, W, MOD, REG, RM})
INSTALT(sbb, {B(100000), S, W, MOD, B(011), RM, DATA, DATA_IF_W})
INSTALT(sbb, {B(0001110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(dec, {B(1111111), W, MOD, B(001), RM})
INSTALT(dec, {B(01001), REG, ImpW(1)})
INST(neg, {B(1111011), W, MOD, B(011), RM})
INST(cmp, {B(001110), D, W, MOD, REG, RM})
INSTALT(cmp, {B(100000), S, W, MOD, B(111), RM, DATA, DATA_IF_W})
INSTALT(cmp, {B(0011110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) // NOTE(casey): The manual table suggests this data is only 8-bit, but wouldn't it be 16 as well?
INST(aas, {B(00111111)})
INST(das, {B(00101111)})
INST(mul, {B(1111011), W, MOD, B(100), RM, ImpS(0)})
INST(imul, {B(1111011), W, MOD, B(101), RM, ImpS(1)})
INST(aam, {B(11010100), B(00001010)}) // NOTE(casey): The manual says this has a DISP... but how could it? What for??
INST(div, {B(1111011), W, MOD, B(110), RM, ImpS(0)})
INST(idiv, {B(1111011), W, MOD, B(111), RM, ImpS(1)})
INST(aad, {B(11010101), B(00001010)})
INST(cbw, {B(10011000)})
INST(cwd, {B(10011001)})
INST(not, {B(1111011), W, MOD, B(010), RM})
INST(shl, {B(110100), V, W, MOD, B(100), RM})
INST(shr, {B(110100), V, W, MOD, B(101), RM})
INST(sar, {B(110100), V, W, MOD, B(111), RM})
INST(rol, {B(110100), V, W, MOD, B(000), RM})
INST(ror, {B(110100), V, W, MOD, B(001), RM})
INST(rcl, {B(110100), V, W, MOD, B(010), RM})
INST(rcr, {B(110100), V, W, MOD, B(011), RM})
INST(and, {B(001000), D, W, MOD, REG, RM})
INSTALT(and, {B(1000000), W, MOD, B(100), RM, DATA, DATA_IF_W})
INSTALT(and, {B(0010010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(test, {B(1000010), W, MOD, REG, RM}) // NOTE(casey): The manual suggests there is a D flag here, but it doesn't appear to be true (it would conflict with xchg if it did)
INSTALT(test, {B(1111011), W, MOD, B(000), RM, DATA, DATA_IF_W})
INSTALT(test, {B(1010100), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) // NOTE(casey): The manual table suggests this data is only 8-bit, but it seems like it could be 16 too?
INST(or, {B(000010), D, W, MOD, REG, RM})
INSTALT(or, {B(1000000), W, MOD, B(001), RM, DATA, DATA_IF_W})
INSTALT(or, {B(0000110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(xor, {B(001100), D, W, MOD, REG, RM})
INSTALT(xor, {B(1000000), W, MOD, B(110), RM, DATA, DATA_IF_W}) // NOTE(casey): The manual has conflicting information about this encoding, but I believe this is the correct binary pattern.
INSTALT(xor, {B(0011010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)})
INST(rep, {B(1111001), Z})
INST(movs, {B(1010010), W})
INST(cmps, {B(1010011), W})
INST(scas, {B(1010111), W})
INST(lods, {B(1010110), W})
INST(stos, {B(1010101), W})
INST(call, {B(11101000), ADDR, Flags(Bits_RelJMPDisp)})
INSTALT(call, {B(11111111), MOD, B(010), RM, ImpW(1)})
INSTALT(call, {B(10011010), ADDR, DATA, DATA_IF_W, ImpW(1)})
INSTALT(call, {B(11111111), MOD, B(011), RM, ImpW(1), Flags(Bits_Far)})
INST(jmp, {B(11101001), ADDR, Flags(Bits_RelJMPDisp)})
INSTALT(jmp, {B(11101011), DISP, Flags(Bits_RelJMPDisp)})
INSTALT(jmp, {B(11111111), MOD, B(100), RM, ImpW(1)})
INSTALT(jmp, {B(11101010), ADDR, DATA, DATA_IF_W, ImpW(1)})
INSTALT(jmp, {B(11111111), MOD, B(101), RM, ImpW(1), Flags(Bits_Far)})
// NOTE(casey): The actual Intel manual does not distinguish mnemonics RET and RETF,
// but NASM needs this to reassemble properly, so we do.
INST(ret, {B(11000011)})
INSTALT(ret, {B(11000010), DATA, DATA_IF_W, ImpW(1)})
INST(retf, {B(11001011)})
INSTALT(retf, {B(11001010), DATA, DATA_IF_W, ImpW(1)})
INST(je, {B(01110100), DISP, Flags(Bits_RelJMPDisp)})
INST(jl, {B(01111100), DISP, Flags(Bits_RelJMPDisp)})
INST(jle, {B(01111110), DISP, Flags(Bits_RelJMPDisp)})
INST(jb, {B(01110010), DISP, Flags(Bits_RelJMPDisp)})
INST(jbe, {B(01110110), DISP, Flags(Bits_RelJMPDisp)})
INST(jp, {B(01111010), DISP, Flags(Bits_RelJMPDisp)})
INST(jo, {B(01110000), DISP, Flags(Bits_RelJMPDisp)})
INST(js, {B(01111000), DISP, Flags(Bits_RelJMPDisp)})
INST(jne, {B(01110101), DISP, Flags(Bits_RelJMPDisp)})
INST(jnl, {B(01111101), DISP, Flags(Bits_RelJMPDisp)})
INST(jg, {B(01111111), DISP, Flags(Bits_RelJMPDisp)})
INST(jnb, {B(01110011), DISP, Flags(Bits_RelJMPDisp)})
INST(ja, {B(01110111), DISP, Flags(Bits_RelJMPDisp)})
INST(jnp, {B(01111011), DISP, Flags(Bits_RelJMPDisp)})
INST(jno, {B(01110001), DISP, Flags(Bits_RelJMPDisp)})
INST(jns, {B(01111001), DISP, Flags(Bits_RelJMPDisp)})
INST(loop, {B(11100010), DISP, Flags(Bits_RelJMPDisp)})
INST(loopz, {B(11100001), DISP, Flags(Bits_RelJMPDisp)})
INST(loopnz, {B(11100000), DISP, Flags(Bits_RelJMPDisp)})
INST(jcxz, {B(11100011), DISP, Flags(Bits_RelJMPDisp)})
INST(int, {B(11001101), DATA})
INST(int3, {B(11001100)}) // TODO(casey): The manual does not suggest that this intrinsic has an "int3" mnemonic, but NASM thinks so
INST(into, {B(11001110)})
INST(iret, {B(11001111)})
INST(clc, {B(11111000)})
INST(cmc, {B(11110101)})
INST(stc, {B(11111001)})
INST(cld, {B(11111100)})
INST(std, {B(11111101)})
INST(cli, {B(11111010)})
INST(sti, {B(11111011)})
INST(hlt, {B(11110100)})
INST(wait, {B(10011011)})
INST(esc, {B(11011), XXX, MOD, YYY, RM})
INST(lock, {B(11110000)})
INST(segment, {B(001), SR, B(110)})
#undef INST
#undef INSTALT
#undef B
#undef D
#undef S
#undef W
#undef V
#undef Z
#undef XXX
#undef YYY
#undef RM
#undef MOD
#undef REG
#undef SR
#undef ImpW
#undef ImpREG
#undef ImpMOD
#undef ImpRM
#undef ImpD
#undef ImpS
#undef DISP
#undef ADDR
#undef DATA
#undef DATA_IF_W
#undef Flags

View File

@ -0,0 +1,21 @@
/* ========================================================================
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Please see https://computerenhance.com for more information
======================================================================== */
#include "sim86.h"
#include "sim86_instruction.h"
#include "sim86_instruction_table.h"
extern "C" u32 Sim86_GetVersion(void);
extern "C" void Sim86_Decode8086Instruction(u32 SourceSize, u8 *Source, instruction *Dest);
extern "C" char const *Sim86_RegisterNameFromOperand(register_access *RegAccess);
extern "C" char const *Sim86_MnemonicFromOperationType(operation_type Type);
extern "C" void Sim86_Get8086InstructionTable(instruction_table *Dest);

BIN
8086_sim/lib/libsim86.so Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,27 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 43
; ========================================================================
bits 16
mov ax, 1
mov bx, 2
mov cx, 3
mov dx, 4
mov sp, 5
mov bp, 6
mov si, 7
mov di, 8

Binary file not shown.

View File

@ -0,0 +1,32 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 44
; ========================================================================
bits 16
mov ax, 1
mov bx, 2
mov cx, 3
mov dx, 4
mov sp, ax
mov bp, bx
mov si, cx
mov di, dx
mov dx, sp
mov cx, bp
mov bx, si
mov ax, di

View File

@ -0,0 +1 @@
И""ЛDDЙffК<66><D09A><EFBFBD>а<EFBFBD>л<EFBFBD>С

View File

@ -0,0 +1,43 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 45
; ========================================================================
bits 16
mov ax, 0x2222
mov bx, 0x4444
mov cx, 0x6666
mov dx, 0x8888
mov ss, ax
mov ds, bx
mov es, cx
mov al, 0x11
mov bh, 0x33
mov cl, 0x55
mov dh, 0x77
mov ah, bl
mov cl, dh
mov ss, ax
mov ds, bx
mov es, cx
mov sp, ss
mov bp, ds
mov si, es
mov di, dx

52
8086_sim/reg_access.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "include/reg_access.h"
#include "include/aliases.h"
#include <stdio.h>
#define REGISTER_COUNT 13
static u16 registers[REGISTER_COUNT] = {0};
void set_register(register_access reg, u16 new_value) {
if (reg.Count == 2) {
registers[reg.Index] = new_value;
return;
}
u16 shift = (u16)(reg.Offset) * (u16)sizeof(u8);
u16 mask = 0xff00;
registers[reg.Index] &= (mask >> shift);
registers[reg.Index] |= (new_value << shift);
}
u16 get_register(register_access reg) {
if (reg.Count == 2) {
return registers[reg.Index];
}
// TODO (Abdelrahman): Implement this
return 0;
}
const char *get_register_name(register_access reg) {
// clang-format off
static const char *register_names[REGISTER_COUNT][3] = {
{"NONE", "NONE", "NONE"},
{"al", "ah", "ax"},
{"bl", "bh", "bx"},
{"cl", "ch", "cx"},
{"dl", "dh", "dx"},
{"sp", "sp", "sp"},
{"bp", "bp", "bp"},
{"si", "si", "si"},
{"di", "di", "di"},
{"es", "es", "es"},
{"cs", "cs", "cs"},
{"ss", "ss", "ss"},
{"ds", "ds", "ds"},
};
// clang-format on
return register_names[reg.Index]
[(reg.Count == 2) ? 2 : (reg.Offset & reg.Count)];
}

BIN
8086_sim/sim86 Normal file

Binary file not shown.

97
8086_sim/sim86.cpp Normal file
View File

@ -0,0 +1,97 @@
#include "include/aliases.h"
#include "include/reg_access.h"
#include "include/sim86_lib.h"
#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
void decode_operand(instruction_operand operand);
void mov_to_register(const register_access &reg,
const instruction_operand &source);
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: sim86 BINARY_FILE\n");
return 1;
}
const char *filename = argv[1];
printf("Filename: %s\n", filename);
FILE *fp = fopen(filename, "rb");
if (!fp) {
printf("Failed to open file %s\n", filename);
}
fseek(fp, 0, SEEK_END);
u32 size = ftell(fp);
fseek(fp, 0, SEEK_SET);
u8 buffer[size + 1];
memset((void *)buffer, 0, size + 1);
fread((void *)buffer, sizeof(u8), size, fp);
fclose(fp);
instruction_table table;
Sim86_Get8086InstructionTable(&table);
u32 offset = 0;
while (offset < size) {
instruction decoded;
Sim86_Decode8086Instruction(size - offset, buffer + offset, &decoded);
if (decoded.Op) {
offset += decoded.Size;
if (decoded.Op == Op_mov) {
instruction_operand dest = decoded.Operands[0];
instruction_operand source = decoded.Operands[1];
if (dest.Type == Operand_Register) {
mov_to_register(dest.Register, source);
printf("%s: 0x%04x\n", get_register_name(dest.Register),
get_register(dest.Register));
}
}
}
}
return 0;
}
void decode_operand(instruction_operand operand) {
switch (operand.Type) {
case Operand_Register:
printf("Register operand: %d, %d, %d\n", operand.Register.Index,
operand.Register.Offset, operand.Register.Count);
break;
case Operand_Memory:
// printf("Memory operand\n");
break;
case Operand_Immediate:
// printf("Immediate operand\n");
break;
default:
break;
}
}
void mov_to_register(const register_access &reg,
const instruction_operand &source) {
switch (source.Type) {
case Operand_Immediate:
set_register(reg, source.Immediate.Value);
break;
case Operand_Register:
set_register(reg, get_register(source.Register));
break;
default:
break;
}
}

BIN
8086_sim/test Normal file

Binary file not shown.

33
8086_sim/test.asm Normal file
View File

@ -0,0 +1,33 @@
bits 16
mov al, 0
mov ah, 0
mov ax, 0
mov bl, 0
mov bh, 0
mov bx, 0
mov cl, 0
mov ch, 0
mov cx, 0
mov dl, 0
mov dh, 0
mov dx, 0
mov sp, 0
mov bp, 0
mov si, 0
mov di, 0
mov es, ax
mov cs, ax
mov ss, ax
mov ds, ax