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