159 lines
2.5 KiB
Odin
159 lines
2.5 KiB
Odin
package sim_8086
|
|
|
|
Register :: enum {
|
|
ax,
|
|
cx,
|
|
dx,
|
|
bx,
|
|
sp,
|
|
bp,
|
|
si,
|
|
di,
|
|
es,
|
|
cs,
|
|
ss,
|
|
ds,
|
|
ip,
|
|
}
|
|
|
|
RegisterValue :: struct #raw_union {
|
|
using _: struct {
|
|
low, high: byte,
|
|
},
|
|
full: i16,
|
|
}
|
|
|
|
Flag :: enum {
|
|
OF,
|
|
SF,
|
|
ZF,
|
|
AF,
|
|
PF,
|
|
CF,
|
|
// NOTE: These are the control flags, previous are status flags, justing noting in
|
|
// case we have to make that distinction in later modeling
|
|
TF,
|
|
DF,
|
|
IF,
|
|
}
|
|
|
|
WordSize :: enum {
|
|
None,
|
|
LastBit,
|
|
FourthBit,
|
|
Always8,
|
|
Always16,
|
|
}
|
|
|
|
None :: struct {}
|
|
|
|
RegisterAccess :: enum {
|
|
Full,
|
|
Low,
|
|
High,
|
|
}
|
|
|
|
RegisterId :: struct {
|
|
name: Register,
|
|
access: RegisterAccess,
|
|
}
|
|
ImmediateSize :: enum {
|
|
_8,
|
|
_16,
|
|
}
|
|
Immediate :: struct {
|
|
value: i16,
|
|
size: ImmediateSize,
|
|
}
|
|
MemoryAddr :: struct {
|
|
addr_id: u8,
|
|
displacement: i16,
|
|
}
|
|
DirectAddress :: distinct i16
|
|
Jump :: distinct i8
|
|
Repeat :: string
|
|
Intersegment :: struct {
|
|
ip: i16,
|
|
cs: i16,
|
|
}
|
|
|
|
Operand :: union {
|
|
None,
|
|
RegisterId,
|
|
Immediate,
|
|
MemoryAddr,
|
|
DirectAddress,
|
|
Jump,
|
|
Repeat,
|
|
Intersegment,
|
|
}
|
|
|
|
OperandInfo :: enum {
|
|
None,
|
|
Register,
|
|
SegmentRegister,
|
|
RegisterMemory,
|
|
Immediate,
|
|
Accumulator,
|
|
DirectAddress,
|
|
Jump,
|
|
VariablePort,
|
|
ShiftRotate,
|
|
Repeat,
|
|
DirectWithinSegment,
|
|
Intersegment,
|
|
}
|
|
|
|
RegisterEncodingBits :: enum {
|
|
None,
|
|
FirstByteLast3,
|
|
SecondByteMiddle3,
|
|
SecondByteLast3,
|
|
FirstByteMiddle3,
|
|
}
|
|
|
|
InstructionInfo :: struct {
|
|
mask: u8,
|
|
encoding: u8,
|
|
opname: Op,
|
|
desc: string,
|
|
src: OperandInfo,
|
|
dst: OperandInfo,
|
|
word_size: WordSize,
|
|
reg_info: RegisterEncodingBits,
|
|
has_flip: bool,
|
|
has_sign_extension: bool,
|
|
check_second_encoding: bool,
|
|
consume_extra_bytes: int,
|
|
shift_rotate_flag: bool,
|
|
}
|
|
|
|
Instruction :: struct {
|
|
opname: Op,
|
|
src: Operand,
|
|
dst: Operand,
|
|
info: InstructionInfo,
|
|
is_word: bool,
|
|
indirect_intersegment: bool,
|
|
// TODO: This is trickier than I thought, it's more than just the one instruction
|
|
// that uses it
|
|
has_segment: Maybe(RegisterId),
|
|
has_lock: bool,
|
|
bytes_read: int,
|
|
segment_offset: int,
|
|
raw_data: []u8,
|
|
debug_msg: string,
|
|
}
|
|
|
|
DecodedInstructions :: struct {
|
|
inst_list: [dynamic]Instruction,
|
|
inst_map: map[int]Instruction,
|
|
total_bytes_decoded: int
|
|
}
|
|
|
|
Cpu :: struct {
|
|
flags: [Flag]bool,
|
|
registers: [Register]RegisterValue,
|
|
memory: [dynamic]u8,
|
|
}
|