diff --git a/Makefile b/Makefile index 9e76042..c71e396 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ bin_files = $(patsubst %.asm,%.bin,$(asm_files)) all: decode asm_files -decode: decode.c lib.h +decode: decode.c decode.h lib.h $(CC) $(CFLAGS) $< -o $@ asm_files: $(bin_files) diff --git a/decode.c b/decode.c index 367f8dd..9ada796 100644 --- a/decode.c +++ b/decode.c @@ -1,130 +1,10 @@ #include #include -#include "lib.h" #include #include #include - -enum InstructionType -{ - INST_MOV_REG_REG = 0b10001000, - // INST_MOV_REG_REG = 0b10001000, - // INST_MOV_REG_REG = 0b10001000, -}; - -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; +#include "lib.h" +#include "decode.h" /// Get Effective Address Calculation Registers char* get_eac_register(char rm) @@ -169,42 +49,6 @@ static u8 mask_and_shift(u8 value, u8 mask) return value; } -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_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}}, -}; - ParsedInstruction parse_instruction(u8* buf) { u8 inst = buf[0]; diff --git a/decode.h b/decode.h new file mode 100644 index 0000000..9318d04 --- /dev/null +++ b/decode.h @@ -0,0 +1,151 @@ +#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; + +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_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}}, +};