performance-aware/instructions.odin

311 lines
14 KiB
Odin

package sim_8086
Op :: enum {
UNKNOWN,
TBD1,
TBD2,
TBD3,
TBD4,
TBD5,
TBD6,
MOV,
PUSH,
POP,
XCHG,
IN,
OUT,
XLAT,
LEA,
LDS,
LES,
LAHF,
SAHF,
PUSHF,
POPF,
ADD,
ADC,
INC,
AAA,
DAA,
SUB,
SBB,
DEC,
NEG,
MUL,
IMUL,
CMP,
AAS,
DAS,
AAM,
DIV,
IDIV,
AAD,
CBW,
CWD,
ROL,
ROR,
RCL,
RCR,
SHL,
SHR,
SAR,
NOT,
TEST,
OR,
AND,
XOR,
REP,
RET,
RETF,
INT,
INT3,
INTO,
IRET,
CLC,
CMC,
STC,
CLD,
STD,
CLI,
STI,
HLT,
WAIT,
ESC,
LOCK,
SEGMENT,
CALL,
JMP,
JNZ,
JNE,
JNGE,
JE,
JZ,
JL,
JLE,
JNG,
JB,
JNAE,
JP,
JPE,
JNA,
JBE,
JO,
JS,
JNL,
JGE,
JNLE,
JG,
JNB,
JAE,
JNBE,
JA,
JNP,
JPO,
JNO,
JNS,
LOOP,
LOOPZ,
LOOPNZ,
LOOPNE,
JCXZ,
}
// TODO: We should figure out another way of handling this case. The way we're doing it
// isn't that great; we return a string with the instruction name, but ideally we have all
// the instructions accounted for, because eventually we will need the final parsed
// instruction to contain all the information related to it
// test_inst := InstructionInfo {
// opname = .NOT, desc = "", mask = 0b11111110, encoding = 0b11110110,
// dst = .RegisterMemory, src = .Immediate, word_size = .LastBit
// }
test_inst := InstructionInfo {
opname = .TEST, desc = "", mask = 0b11111110, encoding = 0b11110110,
dst = .RegisterMemory, src = .Immediate, word_size = .LastBit
}
instructions := [?]InstructionInfo {
{ opname = .TBD1, desc = "Immediate to accumulator",
mask = 0b11000110, encoding = 0b00000100, check_second_encoding = true,
dst = .Accumulator, src = .Immediate,
word_size = .LastBit, },
{ opname = .TBD2, desc = "", check_second_encoding = true,
mask = 0b11111110, encoding = 0b11111110,
src = .RegisterMemory,
word_size = .LastBit, },
{ opname = .TBD3, desc = "", check_second_encoding = true,
mask = 0b11000100, encoding = 0b00000000,
dst = .RegisterMemory, src = .Register,
word_size = .LastBit, reg_info = .SecondByteMiddle3, has_flip = true },
{ opname = .TBD4, desc = "", check_second_encoding = true,
mask = 0b11111100, encoding = 0b10000000,
dst = .RegisterMemory, src = .Immediate,
word_size = .LastBit, has_sign_extension = true },
{ opname = .TBD5, desc = "", check_second_encoding = true,
mask = 0b11111110, encoding = 0b11110110,
// dst = .Immediate, src = .RegisterMemory, word_size = .LastBit, },
src = .RegisterMemory, word_size = .LastBit, },
{ opname = .TBD6, desc = "", check_second_encoding = true,
mask = 0b11111100, encoding = 0b11010000,
dst = .RegisterMemory, src = .ShiftRotate, word_size = .LastBit, },
{ opname = .MOV, desc = "Register/memory to/from register",
mask = 0b11111100, encoding = 0b10001000,
dst = .RegisterMemory, src = .Register,
word_size = .LastBit, reg_info = .SecondByteMiddle3, has_flip = true },
{ opname = .MOV, desc = "Immediate to register/memory",
mask = 0b11111110, encoding = 0b11000110,
dst = .RegisterMemory, src = .Immediate,
word_size = .LastBit, },
{ opname = .MOV, desc = "Immediate to register",
mask = 0b11110000, encoding = 0b10110000,
dst = .Register, src = .Immediate,
word_size = .FourthBit, reg_info = .FirstByteLast3 },
{ opname = .MOV, desc = "Memory to accumulator",
mask = 0b11111110, encoding = 0b10100000,
dst = .Accumulator, src = .DirectAddress,
word_size = .LastBit, },
{ opname = .MOV, desc = "Accumulator to memory",
mask = 0b11111110, encoding = 0b10100010,
dst = .DirectAddress, src = .Accumulator,
word_size = .LastBit, },
// NOTE: There's another instruction but it seems like it just flips, and while not specified
// it seems like it has an undocumented flip bit just like the others
{ opname = .MOV, desc = "Register/memory to segment register",
mask = 0b11111101, encoding = 0b10001100,
dst = .RegisterMemory, src = .SegmentRegister,
reg_info = .SecondByteMiddle3, word_size = .Always16, has_flip = true },
{ opname = .PUSH, desc = "", mask = 0b11111000, encoding = 0b01010000,
src = .Register, reg_info = .FirstByteLast3,
word_size = .Always16, },
{ opname = .PUSH, desc = "", mask = 0b11100111, encoding = 0b00000110,
src = .SegmentRegister, reg_info = .FirstByteMiddle3,
word_size = .Always16, },
{ opname = .POP, desc = "", mask = 0b11111111, encoding = 0b10001111,
src = .RegisterMemory, word_size = .Always16 },
{ opname = .POP, desc = "", mask = 0b11111000, encoding = 0b01011000,
src = .Register, reg_info = .FirstByteLast3,
word_size = .Always16, },
{ opname = .POP, desc = "", mask = 0b11100111, encoding = 0b00000111,
src = .SegmentRegister, reg_info = .FirstByteMiddle3,
word_size = .Always16, },
{ opname = .XCHG, desc = "", mask = 0b11111110, encoding = 0b10000110,
dst = .RegisterMemory, src = .Register,
reg_info = .SecondByteMiddle3, word_size = .LastBit, has_flip = true },
{ opname = .XCHG, desc = "", mask = 0b11111000, encoding = 0b10010000,
dst = .Accumulator, src = .Register,
reg_info = .FirstByteLast3, has_flip = true, word_size = .Always16 },
{ opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11100100,
dst = .Accumulator, src = .ImmediateUnsigned },
{ opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11101100,
dst = .Accumulator, src = .VariablePort,
word_size = .LastBit, },
{ opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11100110,
dst = .ImmediateUnsigned, src = .Accumulator,
word_size = .LastBit, },
{ opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11101110,
dst = .VariablePort, src = .Accumulator,
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 = .LEA, desc = "", mask = 0b11111111, encoding = 0b10001101,
dst = .Register, src = .RegisterMemory,
reg_info = .SecondByteMiddle3, word_size = .Always16 },
{ opname = .LDS, desc = "", mask = 0b11111111, encoding = 0b11000101,
dst = .Register, src = .RegisterMemory,
reg_info = .SecondByteMiddle3, word_size = .Always16 },
{ opname = .LES, desc = "", mask = 0b11111111, encoding = 0b11000100,
dst = .Register, src = .RegisterMemory,
reg_info = .SecondByteMiddle3, word_size = .Always16 },
{ opname = .LAHF, desc = "", mask = 0b11111111, encoding = 0b10011111,},
{ opname = .SAHF, desc = "", mask = 0b11111111, encoding = 0b10011110,},
{ opname = .PUSHF, desc = "", mask = 0b11111111, encoding = 0b10011100,},
{ opname = .POPF, desc = "", mask = 0b11111111, encoding = 0b10011101,},
{ opname = .INC, desc = "", mask = 0b11111000, encoding = 0b01000000,
src = .Register, reg_info = .FirstByteLast3, word_size = .Always16 },
{ opname = .AAA, desc = "", mask = 0b11111111, encoding = 0b00110111,},
{ opname = .DAA, desc = "", mask = 0b11111111, encoding = 0b00100111,},
{ opname = .DEC, desc = "", mask = 0b11111000, encoding = 0b01001000,
src = .Register, reg_info = .FirstByteLast3, word_size = .Always16 },
{ opname = .AAS, desc = "", mask = 0b11111111, encoding = 0b00111111,},
{ opname = .DAS, desc = "", mask = 0b11111111, encoding = 0b00101111,},
{ opname = .AAM, desc = "", mask = 0b11111111, encoding = 0b11010100,},
{ opname = .AAD, desc = "", mask = 0b11111111, encoding = 0b11010101, consume_extra_bytes = 1 },
{ opname = .CBW, desc = "", mask = 0b11111111, encoding = 0b10011000,},
{ opname = .CWD, desc = "", mask = 0b11111111, encoding = 0b10011001,},
{ opname = .TEST, desc = "", mask = 0b11111100, encoding = 0b10000100,
dst = .RegisterMemory, src = .Register,
word_size = .LastBit, reg_info = .SecondByteMiddle3, has_flip = true },
{ opname = .REP, desc = "", mask = 0b11111110, encoding = 0b11110010, src = .Repeat },
{ opname = .RET, desc = "", mask = 0b11111111, encoding = 0b11000011,},
{ opname = .RET, src = .Immediate, word_size = .Always16,
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 = .INT3, desc = "", mask = 0b11111111, encoding = 0b11001100,},
{ opname = .INTO, desc = "", mask = 0b11111111, encoding = 0b11001110,},
{ opname = .IRET, desc = "", mask = 0b11111111, encoding = 0b11001111,},
{ opname = .CLC, desc = "", mask = 0b11111111, encoding = 0b11111000,},
{ opname = .CMC, desc = "", mask = 0b11111111, encoding = 0b11110101,},
{ opname = .STC, desc = "", mask = 0b11111111, encoding = 0b11111001,},
{ opname = .CLD, desc = "", mask = 0b11111111, encoding = 0b11111100,},
{ opname = .STD, desc = "", mask = 0b11111111, encoding = 0b11111101,},
{ opname = .CLI, desc = "", mask = 0b11111111, encoding = 0b11111010,},
{ opname = .STI, desc = "", mask = 0b11111111, encoding = 0b11111011,},
{ opname = .HLT, desc = "", mask = 0b11111111, encoding = 0b11110100,},
{ opname = .WAIT, desc = "", mask = 0b11111111, encoding = 0b10011011,},
{ opname = .LOCK, desc = "", mask = 0b11111111, encoding = 0b11110000,},
{ 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 = .JZ, mask = 0b11111111, encoding = 0b01110100, src = .Jump, desc = "Jump on not zero", },
{ opname = .JL, mask = 0b11111111, encoding = 0b01111100, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNGE, mask = 0b11111111, encoding = 0b01111100, src = .Jump, desc = "Jump on not zero", },
{ opname = .JLE, mask = 0b11111111, encoding = 0b01111110, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNG, mask = 0b11111111, encoding = 0b01111110, src = .Jump, desc = "Jump on not zero", },
{ opname = .JB, mask = 0b11111111, encoding = 0b01110010, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNAE, mask = 0b11111111, encoding = 0b01110010, src = .Jump, desc = "Jump on not zero", },
{ opname = .JBE, mask = 0b11111111, encoding = 0b01110110, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNA, mask = 0b11111111, encoding = 0b01110110, src = .Jump, desc = "Jump on not zero", },
{ opname = .JP, mask = 0b11111111, encoding = 0b01111010, src = .Jump, desc = "Jump on not zero", },
{ opname = .JPE, mask = 0b11111111, encoding = 0b01111010, src = .Jump, desc = "Jump on not zero", },
{ opname = .JO, mask = 0b11111111, encoding = 0b01110000, src = .Jump, desc = "Jump on not zero", },
{ opname = .JS, mask = 0b11111111, encoding = 0b01111000, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNE, mask = 0b11111111, encoding = 0b01110101, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNZ, mask = 0b11111111, encoding = 0b01110101, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNL, mask = 0b11111111, encoding = 0b01111101, src = .Jump, desc = "Jump on not zero", },
{ opname = .JGE, mask = 0b11111111, encoding = 0b01111101, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNLE, mask = 0b11111111, encoding = 0b01111111, src = .Jump, desc = "Jump on not zero", },
{ opname = .JG, mask = 0b11111111, encoding = 0b01111111, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNB, mask = 0b11111111, encoding = 0b01110011, src = .Jump, desc = "Jump on not zero", },
{ opname = .JAE, mask = 0b11111111, encoding = 0b01110011, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNBE, mask = 0b11111111, encoding = 0b01110111, src = .Jump, desc = "Jump on not zero", },
{ opname = .JA, mask = 0b11111111, encoding = 0b01110111, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNP, mask = 0b11111111, encoding = 0b01111011, src = .Jump, desc = "Jump on not zero", },
{ opname = .JPO, mask = 0b11111111, encoding = 0b01111011, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNO, mask = 0b11111111, encoding = 0b01110001, src = .Jump, desc = "Jump on not zero", },
{ opname = .JNS, mask = 0b11111111, encoding = 0b01111001, src = .Jump, desc = "Jump on not zero", },
{ opname = .LOOP, mask = 0b11111111, encoding = 0b11100010, src = .Jump, desc = "Jump on not zero", },
{ opname = .LOOPZ, mask = 0b11111111, encoding = 0b11100001, src = .Jump, desc = "Jump on not zero", },
{ opname = .LOOPNZ, mask = 0b11111111, encoding = 0b11100000, src = .Jump, desc = "Jump on not zero", },
{ opname = .JCXZ, mask = 0b11111111, encoding = 0b11100011, src = .Jump, desc = "Jump on not zero", },
}