Generalizing data and operand bracketing, to make add instrunction work

This commit is contained in:
Joseph Ferano 2025-02-21 23:35:24 +07:00
parent bc0a8b65eb
commit 446848dffb

View File

@ -61,8 +61,9 @@ InstructionInfo :: struct {
has_displacement: bool, has_displacement: bool,
has_segreg: bool, has_segreg: bool,
has_flip: bool, has_flip: bool,
has_bracketed_immediate: bool,
has_explicit_size: bool, has_explicit_size: bool,
has_accumulator: bool, has_sign_extension: bool,
} }
reg_first_last := RegInfo{ in_first_byte = true, shift_offset = 0 } reg_first_last := RegInfo{ in_first_byte = true, shift_offset = 0 }
@ -74,22 +75,28 @@ instructions := [?]InstructionInfo {
word_size = LastBit{}, has_flip = true }, word_size = LastBit{}, has_flip = true },
{ name = "mov", desc = "Immediate to register/memory", mask = 0b11111110, encoding = 0b11000110, { name = "mov", desc = "Immediate to register/memory", mask = 0b11111110, encoding = 0b11000110,
has_mod_rm = true, reg_info = nil, has_data = true, has_displacement = true, has_mod_rm = true, reg_info = nil, has_data = true, has_displacement = true,
word_size = LastBit{}, has_explicit_size = true }, word_size = LastBit{}, has_bracketed_immediate = false, has_explicit_size = true },
{ name = "mov", desc = "Immediate to register", mask = 0b11110000, encoding = 0b10110000, { name = "mov", desc = "Immediate to register", mask = 0b11110000, encoding = 0b10110000,
has_mod_rm = false, reg_info = reg_first_last, has_data = true, has_displacement = false, has_mod_rm = false, reg_info = reg_first_last, has_data = true, has_displacement = false,
word_size = FourthBit{} }, word_size = FourthBit{} },
{ name = "mov", desc = "Memory to accumulator", mask = 0b11111110, encoding = 0b10100000, { name = "mov", desc = "Memory to accumulator", mask = 0b11111110, encoding = 0b10100000,
has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true, has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true,
word_size = LastBit{}, has_accumulator = true }, word_size = LastBit{}, has_bracketed_immediate = true },
{ name = "mov", desc = "Accumulator to memory", mask = 0b11111110, encoding = 0b10100010, { name = "mov", desc = "Accumulator to memory", mask = 0b11111110, encoding = 0b10100010,
has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true, has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true,
word_size = LastBit{}, has_accumulator = true }, word_size = LastBit{}, has_bracketed_immediate = true },
{ name = "mov", desc = "Register/memory to segment register", mask = 0b11111111, encoding = 0b10001110, { name = "mov", desc = "Register/memory to segment register", mask = 0b11111111, encoding = 0b10001110,
has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true, has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true,
word_size = None{} }, word_size = None{} },
{ name = "mov", desc = "Segment register to register/memory", mask = 0b11111111, encoding = 0b10001100, { name = "mov", desc = "Segment register to register/memory", mask = 0b11111111, encoding = 0b10001100,
has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true, has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true,
word_size = None{} }, word_size = None{} },
{ name = "add", desc = "Register/memory to/from register", mask = 0b11111100, encoding = 0b00000000,
has_mod_rm = true, reg_info = reg_second_middle, has_data = false, has_displacement = true,
word_size = LastBit{}, has_flip = true },
{ name = "add", desc = "Immediate to register/memory", mask = 0b11111110, encoding = 0b10000000,
has_mod_rm = true, reg_info = nil, has_data = true, has_displacement = true,
word_size = LastBit{}, has_sign_extension = true },
} }
None :: struct {} None :: struct {}
@ -129,17 +136,11 @@ MemoryAddr :: struct {
addr_id: u8, addr_id: u8,
displacement: Displacement displacement: Displacement
} }
DirectAddress :: distinct i16
Accumulator8 :: distinct i8
Accumulator16 :: distinct i16
OperandType :: union { OperandType :: union {
RegisterId, RegisterId,
Immediate8, Immediate8,
Immediate16, Immediate16,
MemoryAddr, MemoryAddr,
DirectAddress,
Accumulator8,
Accumulator16,
} }
inst_map := make(map[u8]InstructionInfo) inst_map := make(map[u8]InstructionInfo)
@ -186,24 +187,19 @@ get_memory_string :: proc(memoryAddr: MemoryAddr) -> string {
return text return text
} }
get_memory_type_string :: proc(mem_type: OperandType, is_word: bool) -> string { get_memory_type_string :: proc(mem_type: OperandType, is_word: bool, bracketed: bool) -> string {
string_val: string
switch val in mem_type { switch val in mem_type {
case RegisterId: case RegisterId:
return is_word ? registers[val].fullname : registers[val].bytename string_val = is_word ? registers[val].fullname : registers[val].bytename
case Immediate8: case Immediate8:
return fmt.aprintf("%d", val) string_val = fmt.aprintf(bracketed ? "[%d]" : "%d", val)
case Immediate16: case Immediate16:
return fmt.aprintf("%d", val) string_val = fmt.aprintf(bracketed ? "[%d]" : "%d", val)
case MemoryAddr: case MemoryAddr:
return get_memory_string(val) string_val = get_memory_string(val)
case DirectAddress:
return fmt.aprintf("[%d]", val)
case Accumulator8:
return fmt.aprintf("[%d]", val)
case Accumulator16:
return fmt.aprintf("[%d]", val)
} }
return "" return string_val
} }
get_i16 :: proc(data: []u8) -> i16 { get_i16 :: proc(data: []u8) -> i16 {
@ -285,7 +281,6 @@ main :: proc() {
processed := 1 processed := 1
curr_byte := data[idx] curr_byte := data[idx]
instruction, ok := try_find_instruction(curr_byte) instruction, ok := try_find_instruction(curr_byte)
if !ok { if !ok {
txt := "unknown instruction" txt := "unknown instruction"
@ -299,6 +294,7 @@ main :: proc() {
is_word: bool is_word: bool
is_immediate := false is_immediate := false
flip_dst := false flip_dst := false
bracket_operand := instruction.has_bracketed_immediate
rm: u8 rm: u8
mod: u8 mod: u8
reg: u8 reg: u8
@ -318,15 +314,19 @@ main :: proc() {
reg = (b >> reg_info.shift_offset) & 0b111 reg = (b >> reg_info.shift_offset) & 0b111
} }
data_idx := idx + 1
if instruction.has_mod_rm { if instruction.has_mod_rm {
mod = data[idx+1] >> 6 mod = data[idx+1] >> 6
rm = data[idx+1] & 0b00000111 rm = data[idx+1] & 0b00000111
data_idx += 1 + ((int)(mod) % 3)
processed += 1 + ((int)(mod) % 3) processed += 1 + ((int)(mod) % 3)
if mod == 0 { if mod == 0 {
if rm == 0b110 { if rm == 0b110 {
lhs2 = (DirectAddress)(get_i16(data[idx+2:])) lhs2 = (Immediate16)(get_i16(data[idx+2:]))
bracket_operand = true
processed += 2 processed += 2
} else { } else {
lhs2 = MemoryAddr{ addr_id = rm , displacement = None{} } lhs2 = MemoryAddr{ addr_id = rm , displacement = None{} }
@ -338,32 +338,25 @@ main :: proc() {
} else if mod == 3 { } else if mod == 3 {
lhs2 = (RegisterId)(registers[rm].code) lhs2 = (RegisterId)(registers[rm].code)
} }
if instruction.has_explicit_size {
imm_idx := idx + 2 + ((int)(mod) % 3)
rhs2 = (OperandType)(is_word ? (Immediate16)(get_i16(data[imm_idx:])) : (Immediate8)(data[imm_idx]))
processed += is_word ? 2 : 1
} else {
rhs2 = (RegisterId)(reg)
}
} else { } else {
lhs2 = (RegisterId)(registers[reg].code) lhs2 = (RegisterId)(registers[reg].code)
if instruction.has_accumulator {
rhs2 = (OperandType)(is_word ? ((Accumulator16)(get_i16(data[idx+1:]))) : ((Accumulator8)(data[idx+1])))
} else {
rhs2 = (OperandType)(is_word ? ((Immediate16)(get_i16(data[idx+1:]))) : ((Immediate8)(data[idx+1])))
} }
if instruction.has_data {
processed += is_word ? 2 : 1 processed += is_word ? 2 : 1
rhs2 = (OperandType)(is_word ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx]))
} else {
rhs2 = (RegisterId)(reg)
} }
if flip_dst { if flip_dst {
lhs2, rhs2 = rhs2, lhs2 lhs2, rhs2 = rhs2, lhs2
} }
lhs := get_memory_type_string(lhs2, is_word) lhs := get_memory_type_string(lhs2, is_word, bracket_operand)
rhs := get_memory_type_string(rhs2, is_word) rhs := get_memory_type_string(rhs2, is_word, bracket_operand)
size_string := instruction.has_explicit_size ? is_word ? "word " : "byte " : "" size_string := instruction.has_explicit_size ? is_word ? "word " : "byte " : ""
full_inst := fmt.aprintf("%s %s, %s%s", instruction.name, lhs, size_string, rhs) full_inst := fmt.aprintf("%s %s, %s%s", instruction.name, lhs, size_string, rhs)
fmt.printf("%s %*[1]s a", full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") fmt.printf("%s %*[1]s", full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;")
for i in 0..<processed { for i in 0..<processed {
fmt.printf(" %08b", data[idx + i]) fmt.printf(" %08b", data[idx + i])
} }