224 lines
6.0 KiB
C

#include "lib.h"
enum Mode
{
MODE_MEM_NO_DIS = 0b00,
MODE_MEM_DIS_08 = 0b01,
MODE_MEM_DIS_16 = 0b10,
MODE_RGSTR_MODE = 0b11,
};
typedef struct Register
{
char* fullname;
char* bytename;
union {
struct {
char low;
char high;
};
u16 full;
} value;
u8 code;
} Register;
Register registers[8] = {
{.code = 0b000, .fullname = "ax", .bytename = "al"},
{.code = 0b001, .fullname = "cx", .bytename = "cl"},
{.code = 0b010, .fullname = "dx", .bytename = "dl"},
{.code = 0b011, .fullname = "bx", .bytename = "bl"},
{.code = 0b100, .fullname = "sp", .bytename = "ah"},
{.code = 0b101, .fullname = "bp", .bytename = "ch"},
{.code = 0b110, .fullname = "si", .bytename = "dh"},
{.code = 0b111, .fullname = "di", .bytename = "bh"},
};
enum OperandType {OPR_T_MEMORY, OPR_T_REGISTER, OPR_T_IMMEDIATE, OPR_T_DIRADDR};
typedef struct Operand
{
enum OperandType tag;
union {
struct Mem {
char *eac_name;
i16 displacement;
u8 mode;
} mem;
struct Reg {
Register value;
bool wide;
} reg;
struct Imm {
i16 value;
u8 direct;
} imm;
struct DirAddr {
i16 value;
} dir_addr;
};
} Operand;
enum ParseRegType { P_REG_NONE, P_REG_MASK, P_REG_FIXED };
typedef struct ParseReg
{
enum ParseRegType tag;
union {
u8 none;
u8 mask;
u8 fixed;
};
} ParseReg;
typedef struct InstFormat
{
u16 id;
char *name;
ParseReg parse_reg;
u8 inst_enc;
u8 mask_inst;
u8 mask_w;
bool has_operands;
bool has_displacement;
bool has_data;
bool has_d;
bool has_w;
bool has_mod;
bool has_rm;
bool has_s;
bool has_SR;
} InstFormat;
typedef struct ParsedInstruction
{
u16 id;
char *name;
u16_opt data;
u16_opt displacement;
u8_opt w;
u8_opt d;
u8_opt s;
u8_opt mod;
u8_opt reg;
u8_opt rm;
u8_opt SR;
u8 is_data_addr;
u8 bytes_read;
} ParsedInstruction;
typedef struct Instruction
{
Operand src_opr;
Operand dst_opr;
i16 data;
char *operation;
u16 id;
} Instruction;
enum InstructionIdentifier
{
_PREFIX_2,
_PREFIX_3,
_PREFIX_6,
_NAME,
_D,
_W,
_S,
_MOD,
_REGISTER,
_ACC,
_RM,
_DISP_LO,
_DISP_HI,
_DATA_W0,
_DATA_W1,
} InstructionIdentifier;
typedef struct ParsedInst
{
u64 progress;
u8 something;
} ParsedInst;
typedef ParsedInst (*inst_parser_f)(ParsedInst);
ParsedInst pre_2(ParsedInst pi) {return pi;}
ParsedInst pre_3(ParsedInst pi) {return pi;}
ParsedInst pre_6(ParsedInst pi) {return pi;}
ParsedInst name(ParsedInst pi) {return pi;}
ParsedInst reg(ParsedInst pi) {return pi;}
ParsedInst w(ParsedInst pi) {return pi;}
ParsedInst d(ParsedInst pi) {return pi;}
ParsedInst s(ParsedInst pi) {return pi;}
ParsedInst mod(ParsedInst pi) {return pi;}
ParsedInst inst(ParsedInst pi) {return pi;}
ParsedInst rm(ParsedInst pi) {return pi;}
ParsedInst disp_lo(ParsedInst pi) {return pi;}
ParsedInst disp_hi(ParsedInst pi) {return pi;}
ParsedInst data_w0(ParsedInst pi) {return pi;}
ParsedInst data_w1(ParsedInst pi) {return pi;}
inst_parser_f inst_funcs[][6][4] =
{
{{pre_2, name, d, w}, {mod, reg, rm}, {disp_lo}, {disp_hi}},
{{pre_6, s, w}, {mod, name, rm}, {disp_lo}, {disp_hi}, {data_w0}, {data_w1}},
{{pre_6, w}, {data_w0}, {data_w1}},
};
enum InstructionIdentifier inst_ids[][6][4] =
{
{{_PREFIX_2, _NAME, _D, _W}, {_MOD, _REGISTER, _RM}, {_DISP_LO}, {_DISP_HI}},
{{_PREFIX_6, _S, _W}, {_MOD, _NAME, _RM}, {_DISP_LO}, {_DISP_HI}, {_DATA_W0}, {_DATA_W1}},
{{_PREFIX_6, _W}, {_DATA_W0}, {_DATA_W1}},
};
typedef struct InstructionParser
{
enum InstructionIdentifier inst_ids[6][4];
} InstructionParser;
// InstructionParser inst_formats[] =
// {
// {{{_PREFIX_2, _NAME, _D, _W}, {_MOD, _REGISTER, _RM}, {_DISP_LO}, {_DISP_HI}}},
// {{{_PREFIX_6, _S, _W}, {_MOD, _NAME, _RM}, {_DISP_LO}, {_DISP_HI}, {_DATA_W0}, {_DATA_W1}}},
// };
InstFormat inst_formats[] =
{
////////
// MOV
////////
// Register/memory to/from register
{.id=1, .name="mov", .inst_enc=0b10001000, .mask_inst=0x3, .mask_w=0x1,
.has_operands=true, .has_displacement=true, .has_d=true, .has_w=true,
.has_mod=true, .has_rm=true, .parse_reg={.tag = P_REG_MASK, .mask=0b00111000} },
// Immediate to register/memory
{.id=2, .name="mov", .inst_enc=0b11000110, .mask_inst=0x1, .mask_w=0x1, .has_operands=true,
.has_displacement=true, .has_data=true, .has_w=true, .has_mod=true, .has_rm=true},
// Immediate to register
{.id=3, .name="mov", .inst_enc=0b10110000, .mask_inst=0xF, .mask_w=0x8,
.parse_reg={.tag = P_REG_MASK, .mask=0b00000111}, .has_data=true, .has_w=true},
// Memory to accumulator | Accumulator to memory using the `d` bit
// even though the manual doesn't specify it
{.id=4, .name="mov", .inst_enc=0b10100000, .mask_inst=0x3, .mask_w=0x1, .has_data=true,
.has_w=true, .has_d=true, .parse_reg={.tag = P_REG_FIXED, .fixed=0x0}},
// Register/memory to segment register and inverse using the `d` bit
{.id=5, .name="mov", .inst_enc=0b10001100, .mask_inst=0x3, .has_SR=true, .has_d=true,
.has_displacement=true, .has_mod=true, .has_rm=true},
////////
// ADD
////////
// Reg/memory with register or either
{.id=6, .name="add", .inst_enc=0b00000000, .mask_inst=0x3, .has_displacement=true,
.mask_w=0x1, .has_operands=true, .has_w=true, .has_d=true, .has_mod=true,
.has_rm=true, .parse_reg={.tag = P_REG_MASK, .mask=0b00111000}},
// Immediate to register/memory
{.id=7, .name="add", .inst_enc=0b10000000, .mask_inst=0x3, .mask_w=0x1, .has_w=true,
.has_s=true, .has_operands=true, .has_displacement=true,
.has_data=true, .has_mod=true, .has_rm=true},
{.id=8, .name="add", .inst_enc=0b00000100, .mask_inst=0x1, .mask_w=0x1,
.has_data=true, .has_w=true, .parse_reg={.tag = P_REG_FIXED, .fixed=0x0}},
};