Last bunch of instructions to get listing 42 fully read

This commit is contained in:
Joseph Ferano 2025-03-12 23:46:47 +07:00
parent babb07cb43
commit fc02debf65
2 changed files with 113 additions and 54 deletions

View File

@ -37,23 +37,14 @@ segment_registers := [4]Register {
variable_port := registers[2] variable_port := registers[2]
total_bytes_processed := 0
RegInfo :: struct { RegInfo :: struct {
in_first_byte: bool, in_first_byte: bool,
shift_offset: u8, shift_offset: u8,
} }
LastBit :: struct{} WordSize :: enum {
FourthBit :: struct{}
Force :: struct{}
WordSize :: union {
None,
LastBit,
FourthBit,
Force,
}
WordSize2 :: enum {
None, None,
LastBit, LastBit,
FourthBit, FourthBit,
@ -95,27 +86,38 @@ ModMode :: union {
RegisterId :: distinct u8 RegisterId :: distinct u8
Immediate8 :: distinct i8 Immediate8 :: distinct i8
Immediate16 :: distinct i16 Immediate16 :: distinct i16
ImmediateU8 :: distinct u8
MemoryAddr :: struct { MemoryAddr :: struct {
addr_id: u8, addr_id: u8,
displacement: Displacement, displacement: Displacement,
segment: Maybe(Register),
} }
DirectAddress :: distinct i16 DirectAddress :: distinct i16
SegmentRegister :: distinct i8 SegmentRegister :: distinct i8
Jump :: distinct i8 Jump :: distinct i8
VariablePort :: struct {} VariablePort :: struct {}
ShiftRotate :: distinct bool
Repeat :: string Repeat :: string
Intersegment :: struct {
ip: i16,
cs: i16,
}
DirectWithinSegment :: distinct u16
Operand :: union { Operand :: union {
None, None,
RegisterId, RegisterId,
Immediate8, Immediate8,
ImmediateU8,
Immediate16, Immediate16,
MemoryAddr, MemoryAddr,
DirectAddress, DirectAddress,
SegmentRegister, SegmentRegister,
Jump, Jump,
VariablePort, VariablePort,
ShiftRotate,
Repeat, Repeat,
DirectWithinSegment,
Intersegment,
} }
OperandInfo :: enum { OperandInfo :: enum {
@ -124,12 +126,15 @@ OperandInfo :: enum {
SegmentRegister, SegmentRegister,
RegisterMemory, RegisterMemory,
Immediate, Immediate,
ImmediateUnsigned,
Accumulator, Accumulator,
DirectAddress, DirectAddress,
Jump, Jump,
VariablePort, VariablePort,
ShiftRotate, ShiftRotate,
Repeat, Repeat,
DirectWithinSegment,
Intersegment,
} }
RegisterEncodingBits :: enum { RegisterEncodingBits :: enum {
@ -147,7 +152,7 @@ InstructionInfo :: struct {
desc: string, desc: string,
src: OperandInfo, src: OperandInfo,
dst: OperandInfo, dst: OperandInfo,
word_size: WordSize2, word_size: WordSize,
reg_info: RegisterEncodingBits, reg_info: RegisterEncodingBits,
has_flip: bool, has_flip: bool,
has_sign_extension: bool, has_sign_extension: bool,
@ -158,6 +163,10 @@ InstructionInfo :: struct {
RIGHT_ALIGN_AMOUNT := 35 RIGHT_ALIGN_AMOUNT := 35
get_i16 :: proc(data: []u8) -> i16 {
return (i16)(data[1]) << 8 | (i16)(data[0])
}
calculate_effective_address :: proc(r_m: u8) -> string { calculate_effective_address :: proc(r_m: u8) -> string {
val: string val: string
switch r_m { switch r_m {
@ -181,7 +190,7 @@ calculate_effective_address :: proc(r_m: u8) -> string {
return val return val
} }
get_memory_string :: proc(memoryAddr: MemoryAddr) -> string { get_memory_string :: proc(memoryAddr: MemoryAddr, has_segment: Maybe(Register)) -> string {
disp: string disp: string
switch value in memoryAddr.displacement { switch value in memoryAddr.displacement {
case None: case None:
@ -196,17 +205,13 @@ get_memory_string :: proc(memoryAddr: MemoryAddr) -> string {
} }
} }
seg_string: string seg_string: string
if segreg, ok := memoryAddr.segment.?; ok { if segreg, ok := has_segment.?; ok {
seg_string = fmt.aprintf("%s:", segreg.fullname) seg_string = fmt.aprintf("%s:", segreg.fullname)
} }
text := fmt.aprintf("%s[%s%s]", seg_string, calculate_effective_address(memoryAddr.addr_id), disp) text := fmt.aprintf("%s[%s%s]", seg_string, calculate_effective_address(memoryAddr.addr_id), disp)
return text return text
} }
get_i16 :: proc(data: []u8) -> i16 {
return (i16)(data[1]) << 8 | (i16)(data[0])
}
parse_displacement :: proc(data: []u8) -> (displacement: Displacement, disp_amount: int) { parse_displacement :: proc(data: []u8) -> (displacement: Displacement, disp_amount: int) {
mod := (data[0] & 0b11000000) >> 6 mod := (data[0] & 0b11000000) >> 6
disp: Displacement = None{} disp: Displacement = None{}
@ -260,16 +265,17 @@ try_find_instruction :: proc(b: u8) -> (InstructionInfo, bool) {
return InstructionInfo{}, false return InstructionInfo{}, false
} }
get_opname :: proc(opname: OpName, data: []u8) -> string { get_opname :: proc(opname: OpName, data: []u8) -> (string, bool) {
name: string name: string
interseg: bool
if opname == .TBD2 { if opname == .TBD2 {
switch data[1] & 0b00111000 >> 3 { switch data[1] & 0b00111000 >> 3 {
case 0b000: name = "inc" case 0b000: name = "inc"
case 0b001: name = "dec" case 0b001: name = "dec"
case 0b010: name = "call" case 0b010: name = "call"
case 0b011: name = "call" case 0b011: name = "call"; interseg = true
case 0b100: name = "jmp" case 0b100: name = "jmp"
case 0b101: name = "jmp" case 0b101: name = "jmp"; interseg = true
case 0b110: name = "push" case 0b110: name = "push"
} }
} else if opname == .TBD5 { } else if opname == .TBD5 {
@ -311,7 +317,7 @@ get_opname :: proc(opname: OpName, data: []u8) -> string {
case 0b111: name = "cmp" case 0b111: name = "cmp"
} }
} }
return name return name, interseg
} }
parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool, has_segreg: Maybe(Register)) -> Operand { parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool, has_segreg: Maybe(Register)) -> Operand {
@ -361,13 +367,13 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
op = (DirectAddress)(get_i16(data[2:])) op = (DirectAddress)(get_i16(data[2:]))
processed^ += 2 processed^ += 2
} else { } else {
op = MemoryAddr{ addr_id = rm , displacement = None{} , segment = has_segreg } op = MemoryAddr{ addr_id = rm , displacement = None{} }
} }
} else if mod == 1 { } else if mod == 1 {
op = MemoryAddr{ addr_id = rm , displacement = (i8)(data[2]) , segment = has_segreg } op = MemoryAddr{ addr_id = rm , displacement = (i8)(data[2]) }
processed^ += 1 processed^ += 1
} else if mod == 2 { } else if mod == 2 {
op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) , segment = has_segreg } op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) }
processed^ += 2 processed^ += 2
} else if mod == 3 { } else if mod == 3 {
op = (RegisterId)(registers[rm].code) op = (RegisterId)(registers[rm].code)
@ -375,12 +381,15 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
operand = op operand = op
case .Immediate: case .Immediate:
data_idx := processed^ data_idx := processed^
word_signed := word word_signed := word
if inst.has_sign_extension { if inst.has_sign_extension {
word_signed &&= data[0] & 0b0000_0010 == 0 word_signed &&= data[0] & 0b0000_0010 == 0
} }
operand = (Operand)(word_signed ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx])) operand = (Operand)(word_signed ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx]))
processed^ += word_signed ? 2 : 1 processed^ += word_signed ? 2 : 1
case .ImmediateUnsigned:
operand = (ImmediateU8)(data[processed^])
processed^ += 1
case .Accumulator: case .Accumulator:
operand = (RegisterId)(registers[0].code) operand = (RegisterId)(registers[0].code)
case .DirectAddress: case .DirectAddress:
@ -394,37 +403,53 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
operand = VariablePort{} operand = VariablePort{}
case .ShiftRotate: case .ShiftRotate:
v_flag := data[0] & 0b10 != 0 v_flag := data[0] & 0b10 != 0
operand = v_flag ? (RegisterId)(registers[1].code) : (Immediate8)(1) operand = (ShiftRotate)(v_flag)
case .Repeat: case .Repeat:
operand = get_repeat_op(data[1]) operand = get_repeat_op(data[1])
processed^ += 1 processed^ += 1
case .DirectWithinSegment:
value := (int)(get_i16(data[1:])) + total_bytes_processed + 3
operand = (DirectWithinSegment)(value)
processed^ += 2
case .Intersegment:
operand = Intersegment {
ip = get_i16(data[1:]),
cs = get_i16(data[3:]),
}
processed^ += 4
} }
return operand return operand
} }
get_operand_string :: proc(operand: Operand, is_word: bool) -> string { get_operand_string :: proc(operand: Operand, is_word: bool, has_segment: Maybe(Register)) -> string {
string_val: string string_val: string
switch val in operand { switch val in operand {
case None: case None:
string_val = "" string_val = ""
case RegisterId: case RegisterId:
string_val = is_word ? registers[val].fullname : registers[val].bytename string_val = is_word ? registers[val].fullname : registers[val].bytename
case Immediate8: case Immediate8, ImmediateU8, Immediate16, DirectWithinSegment:
string_val = fmt.aprintf("%d", val)
case Immediate16:
string_val = fmt.aprintf("%d", val) string_val = fmt.aprintf("%d", val)
case MemoryAddr: case MemoryAddr:
string_val = get_memory_string(val) string_val = get_memory_string(val, has_segment)
case DirectAddress: case DirectAddress:
string_val = fmt.aprintf("[%d]", val) seg_string: string
if segreg, ok := has_segment.?; ok {
seg_string = fmt.aprintf("%s:", segreg.fullname)
}
string_val = fmt.aprintf("%s[%d]", seg_string, val)
case SegmentRegister: case SegmentRegister:
string_val = segment_registers[val].fullname string_val = segment_registers[val].fullname
case Jump: case Jump:
string_val = fmt.aprintf("$%s%d", val >= 0 ? "+" : "", val) string_val = fmt.aprintf("$%s%d", val >= 0 ? "+" : "", val)
case VariablePort: case VariablePort:
string_val = variable_port.fullname string_val = variable_port.fullname
case ShiftRotate:
string_val = val ? registers[1].bytename : "1"
case Repeat: case Repeat:
string_val = (string)(val) string_val = (string)(val)
case Intersegment:
string_val = fmt.aprintf("%d:%d", val.cs, val.ip)
} }
return string_val return string_val
} }
@ -447,7 +472,8 @@ main :: proc() {
if false { if false {
os.exit(0) os.exit(0)
} }
// asdf :u16 = 0b00000011_11101000
// asdf :u16 = 0b00000110_11011101
// asdf2 :i16 = (i16)(asdf) // asdf2 :i16 = (i16)(asdf)
// fmt.printfln("%d", asdf2) // fmt.printfln("%d", asdf2)
print_at_end := false print_at_end := false
@ -462,7 +488,7 @@ main :: proc() {
repeating_op_count := 0 repeating_op_count := 0
instruction_builder := strings.builder_make() instruction_builder := strings.builder_make()
instruction_list := make([dynamic]string, 512) instruction_list := make([dynamic]string, 512)
fmt.println("bits 16") fmt.println("bits 16\n")
for idx < bytes_read { for idx < bytes_read {
processed := 1 processed := 1
curr_byte := data[idx] curr_byte := data[idx]
@ -491,6 +517,8 @@ main :: proc() {
has_segment = segment_registers[reg] has_segment = segment_registers[reg]
idx += 1 idx += 1
continue continue
} else if inst.opname == .AAM {
processed += 1
} }
src_opr: Operand src_opr: Operand
@ -498,6 +526,7 @@ main :: proc() {
word: bool word: bool
flip: bool flip: bool
indirect_intersegment: bool
op: Operand op: Operand
if inst.has_flip { if inst.has_flip {
@ -513,11 +542,15 @@ main :: proc() {
opname: string opname: string
// TODO: Figure out a way to do this in the string builder // TODO: Figure out a way to do this in the string builder
if inst.check_second_encoding { if inst.check_second_encoding {
opname = strings.to_lower(fmt.aprintf("%s", get_opname(inst.opname, data[idx:]))) op,interseg := get_opname(inst.opname, data[idx:])
indirect_intersegment = interseg
opname = strings.to_lower(fmt.aprintf("%s", op))
// NOTE: This is a special case because it matches the bit pattern of .TBD5, // NOTE: This is a special case because it matches the bit pattern of .TBD5,
// but the instruction itself is different // but the instruction itself is different
if opname == "not" { if opname == "test" && (curr_byte & 0xFF) == 0b11110110 {
inst = not_inst inst = test_inst
// } else if opname == "neg" {
// inst = neg_inst
} }
} else { } else {
opname = strings.to_lower(fmt.aprintf("%s", inst.opname)) opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
@ -541,16 +574,20 @@ main :: proc() {
src_opr, dst_opr = dst_opr, src_opr src_opr, dst_opr = dst_opr, src_opr
} }
dst_str := get_operand_string(dst_opr, word) dst_str := get_operand_string(dst_opr, word, has_segment)
src_str := get_operand_string(src_opr, word) src_str := get_operand_string(src_opr, word, has_segment)
full_inst: string full_inst: string
if dst_str == "" { if dst_str == "" {
_,ok_1 := src_opr.(MemoryAddr); _,ok_1 := src_opr.(MemoryAddr);
_,ok_2 := src_opr.(DirectAddress); _,ok_2 := src_opr.(DirectAddress);
if (ok_1 || ok_2) && inst.word_size != .Always16 { if (ok_1 || ok_2) {
size_string = word ? "word " : "byte " size_string = word ? "word " : "byte "
} }
full_inst = fmt.aprintf("%s %s%s", opname, size_string, src_str) interseg_string: string
if indirect_intersegment {
interseg_string = " far"
}
full_inst = fmt.aprintf("%s%s %s%s", opname, interseg_string, size_string, src_str)
} else { } else {
// NOTE: I don't know why this is the case, but only the move has the word/byte // NOTE: I don't know why this is the case, but only the move has the word/byte
// keyword next to the immediate, but other instructions have it on the memory address // keyword next to the immediate, but other instructions have it on the memory address
@ -568,13 +605,19 @@ main :: proc() {
lock_string = "lock " lock_string = "lock "
} }
fmt.sbprintf(&instruction_builder, "%s%s %*[2]s", lock_string, full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") fmt.sbprintf(&instruction_builder, "%s%s %*[2]s", lock_string, full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;")
if has_lock {
fmt.sbprintf(&instruction_builder, " lock")
}
if _,ok := has_segment.?; ok {
fmt.sbprintf(&instruction_builder, " segment")
}
for i in 0..<processed { for i in 0..<processed {
fmt.sbprintf(&instruction_builder, " %08b", data[idx + i]) fmt.sbprintf(&instruction_builder, " %08b", data[idx + i])
} }
op2 := strings.to_string(instruction_builder) op2 := strings.to_string(instruction_builder)
if op2[0:3] != string(last_opname[:]) { if op2[0:3] != string(last_opname[:]) {
if repeating_op_count > 1 { if repeating_op_count > 0 {
fmt.println() fmt.println()
} }
repeating_op_count = 0 repeating_op_count = 0
@ -588,6 +631,7 @@ main :: proc() {
strings.builder_reset(&instruction_builder) strings.builder_reset(&instruction_builder)
has_lock = false has_lock = false
has_segment = nil has_segment = nil
total_bytes_processed = idx
} }
if print_at_end { if print_at_end {
for i in 0..<line_count { for i in 0..<line_count {

View File

@ -43,6 +43,7 @@ OpName :: enum {
TEST, TEST,
REP, REP,
RET, RET,
RETF,
INT, INT,
INT3, INT3,
INTO, INTO,
@ -59,6 +60,7 @@ OpName :: enum {
ESC, ESC,
LOCK, LOCK,
SEGMENT, SEGMENT,
CALL,
JMP, JMP,
JNZ, JNZ,
JNGE, JNGE,
@ -94,12 +96,11 @@ OpName :: enum {
JCXZ, JCXZ,
} }
not_inst := InstructionInfo { test_inst := InstructionInfo {
opname = .NOT, desc = "", mask = 0b11111110, encoding = 0b11110110, opname = .NOT, desc = "", mask = 0b11111110, encoding = 0b11110110,
src = .RegisterMemory, word_size = .LastBit dst = .RegisterMemory, src = .Immediate, word_size = .LastBit
} }
instructions := [?]InstructionInfo { instructions := [?]InstructionInfo {
{ opname = .TBD1, desc = "Immediate to accumulator", { opname = .TBD1, desc = "Immediate to accumulator",
mask = 0b11000110, encoding = 0b00000100, check_second_encoding = true, mask = 0b11000110, encoding = 0b00000100, check_second_encoding = true,
@ -119,7 +120,8 @@ instructions := [?]InstructionInfo {
word_size = .LastBit, has_sign_extension = true }, word_size = .LastBit, has_sign_extension = true },
{ opname = .TBD5, desc = "", check_second_encoding = true, { opname = .TBD5, desc = "", check_second_encoding = true,
mask = 0b11111110, encoding = 0b11110110, mask = 0b11111110, encoding = 0b11110110,
dst = .Immediate, src = .RegisterMemory, word_size = .LastBit, }, // dst = .Immediate, src = .RegisterMemory, word_size = .LastBit, },
src = .RegisterMemory, word_size = .LastBit, },
{ opname = .TBD6, desc = "", check_second_encoding = true, { opname = .TBD6, desc = "", check_second_encoding = true,
mask = 0b11111100, encoding = 0b11010000, mask = 0b11111100, encoding = 0b11010000,
dst = .RegisterMemory, src = .ShiftRotate, word_size = .LastBit, }, dst = .RegisterMemory, src = .ShiftRotate, word_size = .LastBit, },
@ -143,6 +145,10 @@ instructions := [?]InstructionInfo {
mask = 0b11111110, encoding = 0b10100010, mask = 0b11111110, encoding = 0b10100010,
dst = .DirectAddress, src = .Accumulator, dst = .DirectAddress, src = .Accumulator,
word_size = .LastBit, }, word_size = .LastBit, },
{ opname = .MOV, desc = "Accumulator to memory",
mask = 0b11111111, encoding = 0b10001100,
dst = .RegisterMemory, src = .SegmentRegister,
reg_info = .SecondByteMiddle3 },
{ opname = .PUSH, desc = "", mask = 0b11111000, encoding = 0b01010000, { opname = .PUSH, desc = "", mask = 0b11111000, encoding = 0b01010000,
src = .Register, reg_info = .FirstByteLast3, src = .Register, reg_info = .FirstByteLast3,
word_size = .Always16, }, word_size = .Always16, },
@ -150,7 +156,7 @@ instructions := [?]InstructionInfo {
src = .SegmentRegister, reg_info = .FirstByteMiddle3, src = .SegmentRegister, reg_info = .FirstByteMiddle3,
word_size = .Always16, }, word_size = .Always16, },
{ opname = .POP, desc = "", mask = 0b11111111, encoding = 0b10001111, { opname = .POP, desc = "", mask = 0b11111111, encoding = 0b10001111,
src = .RegisterMemory,}, src = .RegisterMemory, word_size = .Always16 },
{ opname = .POP, desc = "", mask = 0b11111000, encoding = 0b01011000, { opname = .POP, desc = "", mask = 0b11111000, encoding = 0b01011000,
src = .Register, reg_info = .FirstByteLast3, src = .Register, reg_info = .FirstByteLast3,
word_size = .Always16, }, word_size = .Always16, },
@ -159,12 +165,12 @@ instructions := [?]InstructionInfo {
word_size = .Always16, }, word_size = .Always16, },
{ opname = .XCHG, desc = "", mask = 0b11111110, encoding = 0b10000110, { opname = .XCHG, desc = "", mask = 0b11111110, encoding = 0b10000110,
dst = .RegisterMemory, src = .Register, dst = .RegisterMemory, src = .Register,
reg_info = .SecondByteMiddle3, has_flip = true }, reg_info = .SecondByteMiddle3, word_size = .LastBit, has_flip = true },
{ opname = .XCHG, desc = "", mask = 0b11111000, encoding = 0b10010000, { opname = .XCHG, desc = "", mask = 0b11111000, encoding = 0b10010000,
dst = .Accumulator, src = .Register, dst = .Accumulator, src = .Register,
reg_info = .FirstByteLast3, has_flip = true, word_size = .Always16 }, reg_info = .FirstByteLast3, has_flip = true, word_size = .Always16 },
{ opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11100100, { opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11100100,
dst = .Accumulator, src = .Immediate, dst = .Accumulator, src = .ImmediateUnsigned,
// TODO: Everything works just fine, but the problem here is that if you want it to // TODO: Everything works just fine, but the problem here is that if you want it to
// show up as an unsigned int, then we have to change the types because the number // show up as an unsigned int, then we have to change the types because the number
// 200, for instance, will show up as a negative, we would have to create an unsigned // 200, for instance, will show up as a negative, we would have to create an unsigned
@ -174,11 +180,13 @@ instructions := [?]InstructionInfo {
dst = .Accumulator, src = .VariablePort, dst = .Accumulator, src = .VariablePort,
word_size = .LastBit, }, word_size = .LastBit, },
{ opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11100110, { opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11100110,
dst = .Immediate, src = .Accumulator, dst = .ImmediateUnsigned, src = .Accumulator,
word_size = .Unsigned8, }, word_size = .LastBit, },
{ opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11101110, { opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11101110,
dst = .VariablePort, src = .Accumulator, dst = .VariablePort, src = .Accumulator,
word_size = .LastBit, }, word_size = .LastBit, },
{ opname = .TEST, desc = "", mask = 0b11111110, encoding = 0b10101000,
dst = .Accumulator, src = .Immediate, word_size = .LastBit },
{ opname = .XLAT, desc = "", mask = 0b11111111, encoding = 0b11010111,}, { opname = .XLAT, desc = "", mask = 0b11111111, encoding = 0b11010111,},
{ opname = .LEA, desc = "", mask = 0b11111111, encoding = 0b10001101, { opname = .LEA, desc = "", mask = 0b11111111, encoding = 0b10001101,
dst = .Register, src = .RegisterMemory, dst = .Register, src = .RegisterMemory,
@ -212,6 +220,9 @@ instructions := [?]InstructionInfo {
{ opname = .RET, desc = "", mask = 0b11111111, encoding = 0b11000011,}, { opname = .RET, desc = "", mask = 0b11111111, encoding = 0b11000011,},
{ opname = .RET, src = .Immediate, word_size = .Always16, { opname = .RET, src = .Immediate, word_size = .Always16,
desc = "", mask = 0b11111111, encoding = 0b11000010,}, desc = "", mask = 0b11111111, encoding = 0b11000010,},
{ opname = .RETF, desc = "", mask = 0b11111111, encoding = 0b11001011,},
{ opname = .RETF, desc = "", mask = 0b11111111, encoding = 0b11001010,
src = .Immediate, word_size = .Always16 },
{ opname = .INT, src = .Immediate, desc = "", mask = 0b11111111, encoding = 0b11001101,}, { opname = .INT, src = .Immediate, desc = "", mask = 0b11111111, encoding = 0b11001101,},
{ opname = .INT3, desc = "", mask = 0b11111111, encoding = 0b11001100,}, { opname = .INT3, desc = "", mask = 0b11111111, encoding = 0b11001100,},
{ opname = .INTO, desc = "", mask = 0b11111111, encoding = 0b11001110,}, { opname = .INTO, desc = "", mask = 0b11111111, encoding = 0b11001110,},
@ -228,6 +239,10 @@ instructions := [?]InstructionInfo {
// { opname = .ESC, desc = "", mask = 0b11111111, encoding = 0b11111000, dst = }, // { opname = .ESC, desc = "", mask = 0b11111111, encoding = 0b11111000, dst = },
{ opname = .LOCK, desc = "", mask = 0b11111111, encoding = 0b11110000,}, { opname = .LOCK, desc = "", mask = 0b11111111, encoding = 0b11110000,},
{ opname = .SEGMENT, desc = "", mask = 0b11100111, encoding = 0b00100110,}, { opname = .SEGMENT, desc = "", mask = 0b11100111, encoding = 0b00100110,},
{ opname = .CALL, desc = "", mask = 0b11111111, encoding = 0b10011010, src = .Intersegment },
{ opname = .JMP, desc = "", mask = 0b11111111, encoding = 0b11101010, src = .Intersegment },
{ opname = .JMP, desc = "", mask = 0b11111111, encoding = 0b11101001, src = .DirectWithinSegment },
{ opname = .CALL, desc = "", mask = 0b11111111, encoding = 0b11101000, src = .DirectWithinSegment },
{ opname = .JE, mask = 0b11111111, encoding = 0b01110100, src = .Jump, desc = "Jump on not zero", }, { opname = .JE, mask = 0b11111111, encoding = 0b01110100, src = .Jump, desc = "Jump on not zero", },
{ opname = .JZ, mask = 0b11111111, encoding = 0b01110100, src = .Jump, desc = "Jump on not zero", }, { opname = .JZ, mask = 0b11111111, encoding = 0b01110100, src = .Jump, desc = "Jump on not zero", },