Types and instruction specifications moved to decode.h
This commit is contained in:
parent
a0ed11416e
commit
26c07aee61
2
Makefile
2
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)
|
||||
|
160
decode.c
160
decode.c
@ -1,130 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib.h"
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
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];
|
||||
|
151
decode.h
Normal file
151
decode.h
Normal file
@ -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}},
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user