#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}}, };