From 4467191198c869d1f9c4ef3f16a84b5542d74f78 Mon Sep 17 00:00:00 2001 From: doyle Date: Thu, 30 Mar 2023 22:37:26 +1100 Subject: [PATCH] sim8086: Store and print from combined struct, S86_Opcode --- part1/sim8086.c | 1499 ++++++++++++++++++++++++----------------------- part1/sim8086.h | 477 +++++++++------ project.rdbg | Bin 2008 -> 1754 bytes 3 files changed, 1047 insertions(+), 929 deletions(-) diff --git a/part1/sim8086.c b/part1/sim8086.c index 5db49f4..a7b2617 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -3,159 +3,264 @@ #include "sim8086_stdlib.c" -S86_RegisterType S86_RegisterTypeFromWReg(bool w, uint8_t reg) +S86_Str8 S86_MnemonicStr8(S86_Mnemonic type) +{ + S86_Str8 result = {0}; + switch (type) { + case S86_Mnemonic_MOV: result = S86_STR8("mov"); break; + case S86_Mnemonic_PUSH: result = S86_STR8("push"); break; + case S86_Mnemonic_POP: result = S86_STR8("pop"); break; + case S86_Mnemonic_XCHG: result = S86_STR8("xchg"); break; + case S86_Mnemonic_IN: result = S86_STR8("in"); break; + case S86_Mnemonic_OUT: result = S86_STR8("out"); break; + case S86_Mnemonic_XLAT: result = S86_STR8("xlat"); break; + case S86_Mnemonic_LEA: result = S86_STR8("lea"); break; + case S86_Mnemonic_LDS: result = S86_STR8("lds"); break; + case S86_Mnemonic_LES: result = S86_STR8("les"); break; + case S86_Mnemonic_LAHF: result = S86_STR8("lahf"); break; + case S86_Mnemonic_SAHF: result = S86_STR8("sahf"); break; + case S86_Mnemonic_PUSHF: result = S86_STR8("pushf"); break; + case S86_Mnemonic_POPF: result = S86_STR8("popf"); break; + case S86_Mnemonic_ADD: result = S86_STR8("add"); break; + case S86_Mnemonic_ADC: result = S86_STR8("adc"); break; + case S86_Mnemonic_INC: result = S86_STR8("inc"); break; + case S86_Mnemonic_AAA: result = S86_STR8("aaa"); break; + case S86_Mnemonic_DAA: result = S86_STR8("daa"); break; + case S86_Mnemonic_SUB: result = S86_STR8("sub"); break; + case S86_Mnemonic_SBB: result = S86_STR8("sbb"); break; + case S86_Mnemonic_DEC: result = S86_STR8("dec"); break; + case S86_Mnemonic_NEG: result = S86_STR8("neg"); break; + case S86_Mnemonic_CMP: result = S86_STR8("cmp"); break; + case S86_Mnemonic_AAS: result = S86_STR8("aas"); break; + case S86_Mnemonic_DAS: result = S86_STR8("das"); break; + case S86_Mnemonic_MUL: result = S86_STR8("mul"); break; + case S86_Mnemonic_IMUL: result = S86_STR8("imul"); break; + case S86_Mnemonic_AAM: result = S86_STR8("aam"); break; + case S86_Mnemonic_DIV: result = S86_STR8("div"); break; + case S86_Mnemonic_IDIV: result = S86_STR8("idiv"); break; + case S86_Mnemonic_AAD: result = S86_STR8("aad"); break; + case S86_Mnemonic_CBW: result = S86_STR8("cbw"); break; + case S86_Mnemonic_CWD: result = S86_STR8("cwd"); break; + case S86_Mnemonic_NOT: result = S86_STR8("not"); break; + case S86_Mnemonic_SHL_SAL: result = S86_STR8("sal"); break; + case S86_Mnemonic_SHR: result = S86_STR8("shr"); break; + case S86_Mnemonic_SAR: result = S86_STR8("sar"); break; + case S86_Mnemonic_ROL: result = S86_STR8("rol"); break; + case S86_Mnemonic_ROR: result = S86_STR8("ror"); break; + case S86_Mnemonic_RCL: result = S86_STR8("rcl"); break; + case S86_Mnemonic_RCR: result = S86_STR8("rcr"); break; + case S86_Mnemonic_AND: result = S86_STR8("and"); break; + case S86_Mnemonic_TEST: result = S86_STR8("test"); break; + case S86_Mnemonic_OR: result = S86_STR8("or"); break; + case S86_Mnemonic_XOR: result = S86_STR8("xor"); break; + case S86_Mnemonic_REP: result = S86_STR8("rep"); break; + case S86_Mnemonic_CALL: result = S86_STR8("call"); break; + case S86_Mnemonic_JMP: result = S86_STR8("jmp"); break; + case S86_Mnemonic_RET: result = S86_STR8("ret"); break; + case S86_Mnemonic_JE_JZ: result = S86_STR8("je"); break; + case S86_Mnemonic_JL_JNGE: result = S86_STR8("jl"); break; + case S86_Mnemonic_JLE_JNG: result = S86_STR8("jle"); break; + case S86_Mnemonic_JB_JNAE: result = S86_STR8("jb"); break; + case S86_Mnemonic_JBE_JNA: result = S86_STR8("jbe"); break; + case S86_Mnemonic_JP_JPE: result = S86_STR8("jp"); break; + case S86_Mnemonic_JO: result = S86_STR8("jo"); break; + case S86_Mnemonic_JS: result = S86_STR8("js"); break; + case S86_Mnemonic_JNE_JNZ: result = S86_STR8("jne"); break; + case S86_Mnemonic_JNL_JGE: result = S86_STR8("jnl"); break; + case S86_Mnemonic_JNLE_JG: result = S86_STR8("jg"); break; + case S86_Mnemonic_JNB_JAE: result = S86_STR8("jnb"); break; + case S86_Mnemonic_JNBE_JA: result = S86_STR8("ja"); break; + case S86_Mnemonic_JNP_JO: result = S86_STR8("jnp"); break; + case S86_Mnemonic_JNO: result = S86_STR8("jno"); break; + case S86_Mnemonic_JNS: result = S86_STR8("jns"); break; + case S86_Mnemonic_LOOP: result = S86_STR8("loop"); break; + case S86_Mnemonic_LOOPZ_LOOPE: result = S86_STR8("loopz"); break; + case S86_Mnemonic_LOOPNZ_LOOPNE: result = S86_STR8("loopnz"); break; + case S86_Mnemonic_JCXZ: result = S86_STR8("jcxz"); break; + case S86_Mnemonic_INT: result = S86_STR8("int"); break; + case S86_Mnemonic_INT3: result = S86_STR8("int3"); break; + case S86_Mnemonic_INTO: result = S86_STR8("into"); break; + case S86_Mnemonic_IRET: result = S86_STR8("iret"); break; + case S86_Mnemonic_CLC: result = S86_STR8("clc"); break; + case S86_Mnemonic_CMC: result = S86_STR8("cmc"); break; + case S86_Mnemonic_STC: result = S86_STR8("stc"); break; + case S86_Mnemonic_CLD: result = S86_STR8("cld"); break; + case S86_Mnemonic_STD: result = S86_STR8("std"); break; + case S86_Mnemonic_CLI: result = S86_STR8("cli"); break; + case S86_Mnemonic_STI: result = S86_STR8("sti"); break; + case S86_Mnemonic_HLT: result = S86_STR8("hlt"); break; + case S86_Mnemonic_WAIT: result = S86_STR8("wait"); break; + case S86_Mnemonic_LOCK: result = S86_STR8("lock"); break; + case S86_Mnemonic_SEGMENT: result = S86_STR8("segment"); break; + } + return result; +} + +S86_MnemonicOp S86_MnemonicOpFromWReg(bool w, uint8_t reg) { S86_ASSERT(reg < 8); - S86_RegisterType const type_table[2][8] = { + S86_MnemonicOp const type_table[2][8] = { [0b0] = { - [0] = S86_RegisterType_AL, - [1] = S86_RegisterType_CL, - [2] = S86_RegisterType_DL, - [3] = S86_RegisterType_BL, - [4] = S86_RegisterType_AH, - [5] = S86_RegisterType_CH, - [6] = S86_RegisterType_DH, - [7] = S86_RegisterType_BH, + [0] = S86_MnemonicOp_AL, + [1] = S86_MnemonicOp_CL, + [2] = S86_MnemonicOp_DL, + [3] = S86_MnemonicOp_BL, + [4] = S86_MnemonicOp_AH, + [5] = S86_MnemonicOp_CH, + [6] = S86_MnemonicOp_DH, + [7] = S86_MnemonicOp_BH, }, [0b1] = { - [0] = S86_RegisterType_AX, - [1] = S86_RegisterType_CX, - [2] = S86_RegisterType_DX, - [3] = S86_RegisterType_BX, - [4] = S86_RegisterType_SP, - [5] = S86_RegisterType_BP, - [6] = S86_RegisterType_SI, - [7] = S86_RegisterType_DI, + [0] = S86_MnemonicOp_AX, + [1] = S86_MnemonicOp_CX, + [2] = S86_MnemonicOp_DX, + [3] = S86_MnemonicOp_BX, + [4] = S86_MnemonicOp_SP, + [5] = S86_MnemonicOp_BP, + [6] = S86_MnemonicOp_SI, + [7] = S86_MnemonicOp_DI, }, }; - S86_RegisterType result = type_table[w][reg]; + S86_MnemonicOp result = type_table[w][reg]; return result; } -S86_SegmentRegisterType S86_SegmentRegisterTypeFromSR(uint8_t sr) +S86_MnemonicOp S86_MnemonicOpFromSR(uint8_t sr) { S86_ASSERT(sr < 4); - S86_SegmentRegisterType result = S86_SegmentRegisterType_ES + sr; + S86_MnemonicOp result = S86_MnemonicOp_ES + sr; return result; } -S86_Str8 S86_SegmentRegisterStr8(S86_SegmentRegisterType type) +S86_Str8 S86_MnemonicOpStr8(S86_MnemonicOp type) { S86_Str8 result = {0}; switch (type) { - case S86_SegmentRegisterType_Invalid: S86_ASSERT(0); break; - case S86_SegmentRegisterType_ES: result = S86_STR8("es"); break; - case S86_SegmentRegisterType_CS: result = S86_STR8("cs"); break; - case S86_SegmentRegisterType_SS: result = S86_STR8("ss"); break; - case S86_SegmentRegisterType_DS: result = S86_STR8("ds"); break; - case S86_SegmentRegisterType_Count: S86_ASSERT(0); break; + case S86_MnemonicOp_Invalid: result = S86_STR8(""); break; + case S86_MnemonicOp_AL: result = S86_STR8("al"); break; + case S86_MnemonicOp_CL: result = S86_STR8("cl"); break; + case S86_MnemonicOp_DL: result = S86_STR8("dl"); break; + case S86_MnemonicOp_BL: result = S86_STR8("bl"); break; + case S86_MnemonicOp_AH: result = S86_STR8("ah"); break; + case S86_MnemonicOp_CH: result = S86_STR8("ch"); break; + case S86_MnemonicOp_DH: result = S86_STR8("dh"); break; + case S86_MnemonicOp_BH: result = S86_STR8("bh"); break; + case S86_MnemonicOp_AX: result = S86_STR8("ax"); break; + case S86_MnemonicOp_CX: result = S86_STR8("cx"); break; + case S86_MnemonicOp_DX: result = S86_STR8("dx"); break; + case S86_MnemonicOp_BX: result = S86_STR8("bx"); break; + case S86_MnemonicOp_SP: result = S86_STR8("sp"); break; + case S86_MnemonicOp_BP: result = S86_STR8("bp"); break; + case S86_MnemonicOp_SI: result = S86_STR8("si"); break; + case S86_MnemonicOp_DI: result = S86_STR8("di"); break; + case S86_MnemonicOp_BX_SI: result = S86_STR8("bx + si"); break; + case S86_MnemonicOp_BX_DI: result = S86_STR8("bx + di"); break; + case S86_MnemonicOp_BP_SI: result = S86_STR8("bp + si"); break; + case S86_MnemonicOp_BP_DI: result = S86_STR8("bp + di"); break; + case S86_MnemonicOp_DirectAddress: result = S86_STR8(""); break; + case S86_MnemonicOp_Immediate: result = S86_STR8(""); break; + case S86_MnemonicOp_ES: result = S86_STR8("es"); break; + case S86_MnemonicOp_CS: result = S86_STR8("cs"); break; + case S86_MnemonicOp_SS: result = S86_STR8("ss"); break; + case S86_MnemonicOp_DS: result = S86_STR8("ds"); break; + case S86_MnemonicOp_MOVS: result = S86_STR8("movs"); break; + case S86_MnemonicOp_CMPS: result = S86_STR8("cmps"); break; + case S86_MnemonicOp_SCAS: result = S86_STR8("scas"); break; + case S86_MnemonicOp_LODS: result = S86_STR8("lods"); break; + case S86_MnemonicOp_STOS: result = S86_STR8("stos"); break; + case S86_MnemonicOp_DirectInterSegment: result = S86_STR8(""); break; + case S86_MnemonicOp_Jump: result = S86_STR8(""); break; } return result; } -S86_Str8 S86_RegisterStr8(S86_RegisterType type) +void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) { - S86_Str8 result = {0}; - switch (type) { - case S86_RegisterType_AL: result = S86_STR8("al"); break; - case S86_RegisterType_CL: result = S86_STR8("cl"); break; - case S86_RegisterType_DL: result = S86_STR8("dl"); break; - case S86_RegisterType_BL: result = S86_STR8("bl"); break; - case S86_RegisterType_AH: result = S86_STR8("ah"); break; - case S86_RegisterType_CH: result = S86_STR8("ch"); break; - case S86_RegisterType_DH: result = S86_STR8("dh"); break; - case S86_RegisterType_BH: result = S86_STR8("bh"); break; - case S86_RegisterType_AX: result = S86_STR8("ax"); break; - case S86_RegisterType_CX: result = S86_STR8("cx"); break; - case S86_RegisterType_DX: result = S86_STR8("dx"); break; - case S86_RegisterType_BX: result = S86_STR8("bx"); break; - case S86_RegisterType_SP: result = S86_STR8("sp"); break; - case S86_RegisterType_BP: result = S86_STR8("bp"); break; - case S86_RegisterType_SI: result = S86_STR8("si"); break; - case S86_RegisterType_DI: result = S86_STR8("di"); break; - case S86_RegisterType_BX_SI: result = S86_STR8("bx + si"); break; - case S86_RegisterType_BX_DI: result = S86_STR8("bx + di"); break; - case S86_RegisterType_BP_SI: result = S86_STR8("bp + si"); break; - case S86_RegisterType_BP_DI: result = S86_STR8("bp + di"); break; - case S86_RegisterType_DirectAddress: result = S86_STR8(""); break; - case S86_RegisterType_Immediate: result = S86_STR8(""); break; + // TODO: It sucks to have these enums that specify source or dest because + // we can't have a nice generic codepath to handle the dest, src mnemonic + // ops without these pre-emptive checks here inorder to make it generic + // here. + // + // It's probably better to just have flags for the src and dest mnemonic op + // and then you can have one code path that just checks the flags on each op + S86_MnemonicOp mnemonic_op = src ? opcode.src : opcode.dest; + + bool wide_prefix = ( src && opcode.wide_prefix == S86_WidePrefix_Src) || + (!src && opcode.wide_prefix == S86_WidePrefix_Dest); + + bool effective_addr = ( src && opcode.effective_addr == S86_EffectiveAddress_Src) || + (!src && opcode.effective_addr == S86_EffectiveAddress_Dest); + + if (mnemonic_op == S86_MnemonicOp_Invalid) + return; + + if (src) + S86_PrintFmt(", "); + else + S86_PrintFmt(" "); + + if (wide_prefix) + S86_PrintFmt("%s ", opcode.wide ? "word" : "byte"); + + if (effective_addr && opcode.seg_reg_prefix != S86_MnemonicOp_Invalid) { + S86_Str8 prefix = S86_MnemonicOpStr8(opcode.seg_reg_prefix); + S86_PrintFmt("%.*s:", S86_STR8_FMT(prefix)); } - return result; + + if (opcode.effective_addr_loads_mem && effective_addr) + S86_Print(S86_STR8("[")); + + if (mnemonic_op == S86_MnemonicOp_DirectAddress) { + S86_PrintFmt("%s%d", + opcode.displacement >= 0 ? "" : "-", + opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); + } else if (mnemonic_op == S86_MnemonicOp_Jump) { + S86_PrintFmt("$+2%c%d", + opcode.displacement > 0 ? '+' : '-', + opcode.displacement > 0 ? opcode.displacement : -opcode.displacement); + } else if (mnemonic_op == S86_MnemonicOp_Immediate) { + S86_PrintFmt("%u", opcode.immediate); + } else if (mnemonic_op == S86_MnemonicOp_DirectInterSegment) { + uint16_t left = (uint32_t)opcode.displacement >> 16; + uint16_t right = (uint32_t)opcode.displacement & 0xFFFF; + S86_PrintFmt("%u:%u", left, right); + } else { + S86_Str8 reg_str8 = S86_MnemonicOpStr8(mnemonic_op); + S86_PrintFmt("%.*s", S86_STR8_FMT(reg_str8)); + + if (mnemonic_op >= S86_MnemonicOp_MOVS && mnemonic_op <= S86_MnemonicOp_STOS) { + S86_PrintFmt("%c", opcode.wide ? 'w' : 'b'); + } + + if (effective_addr && opcode.displacement) { + S86_PrintFmt(" %c %d", + opcode.displacement >= 0 ? '+' : '-', + opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); + } + } + + if (effective_addr && opcode.effective_addr_loads_mem) + S86_Print(S86_STR8("]")); } -void S86_PrintAsmOp(S86_AsmOp asm_op) +void S86_PrintOpcode(S86_Opcode opcode) { - S86_Print(S86_STR8(" ")); - { - if (asm_op.wide_prefix == S86_WidePrefix_Dest) - S86_PrintFmt("%s ", asm_op.wide ? "word" : "byte"); + if (opcode.mnemonic == S86_Mnemonic_SEGMENT) + return; - if (asm_op.has_displacement && asm_op.effective_addr == S86_EffectiveAddress_Dest) - S86_Print(S86_STR8("[")); + S86_Str8 mnemonic = S86_MnemonicStr8(opcode.mnemonic); + S86_PrintFmt("%.*s", S86_STR8_FMT(mnemonic)); + S86_PrintOpcodeMnemonicOp(opcode, false /*src*/); + S86_PrintOpcodeMnemonicOp(opcode, true /*dest*/); - if (asm_op.effective_addr == S86_EffectiveAddress_Dest && asm_op.seg_reg != S86_SegmentRegisterType_Invalid) { - S86_Str8 seg_reg_str8 = S86_SegmentRegisterStr8(asm_op.seg_reg); - S86_PrintFmt("%.*s:", S86_STR8_FMT(seg_reg_str8)); - } - - if (asm_op.dest == S86_RegisterType_DirectAddress) { - S86_PrintFmt("%s%d", - asm_op.displacement >= 0 ? "" : "-", - asm_op.displacement >= 0 ? asm_op.displacement : -asm_op.displacement); - } else if (asm_op.dest == S86_RegisterType_Immediate) { - S86_PrintFmt("%u", asm_op.immediate); - } else { - S86_Str8 reg_str8 = S86_RegisterStr8(asm_op.dest); - S86_PrintFmt("%.*s", S86_STR8_FMT(reg_str8)); - if (asm_op.effective_addr == S86_EffectiveAddress_Dest && asm_op.displacement) { - S86_PrintFmt(" %c %d", - asm_op.displacement >= 0 ? '+' : '-', - asm_op.displacement >= 0 ? asm_op.displacement : -asm_op.displacement); - } - } - if (asm_op.has_displacement && asm_op.effective_addr == S86_EffectiveAddress_Dest) - S86_Print(S86_STR8("]")); - } - S86_PrintFmt(", "); - { - if (asm_op.wide_prefix == S86_WidePrefix_Src) - S86_PrintFmt("%s ", asm_op.wide ? "word" : "byte"); - - if (asm_op.has_displacement && asm_op.effective_addr == S86_EffectiveAddress_Src) - S86_Print(S86_STR8("[")); - - if (asm_op.effective_addr == S86_EffectiveAddress_Src && asm_op.seg_reg != S86_SegmentRegisterType_Invalid) { - S86_Str8 seg_reg_str8 = S86_SegmentRegisterStr8(asm_op.seg_reg); - S86_PrintFmt("%.*s:", S86_STR8_FMT(seg_reg_str8)); - } - - if (asm_op.src == S86_RegisterType_DirectAddress) { - S86_PrintFmt("%s%d", - asm_op.displacement >= 0 ? "" : "-", - asm_op.displacement >= 0 ? asm_op.displacement : -asm_op.displacement); - } else if (asm_op.src == S86_RegisterType_Immediate) { - S86_PrintFmt("%u", asm_op.immediate); - } else { - S86_Str8 reg_str8 = S86_RegisterStr8(asm_op.src); - S86_PrintFmt("%.*s", S86_STR8_FMT(reg_str8)); - if (asm_op.effective_addr == S86_EffectiveAddress_Src && asm_op.displacement) { - S86_PrintFmt(" %c %d", - asm_op.displacement >= 0 ? '+' : '-', - asm_op.displacement >= 0 ? asm_op.displacement : -asm_op.displacement); - } - } - if (asm_op.has_displacement && asm_op.effective_addr == S86_EffectiveAddress_Src) - S86_Print(S86_STR8("]")); - } - S86_Print(S86_STR8("\n")); + if (opcode.mnemonic == S86_Mnemonic_LOCK) + S86_Print(S86_STR8(" ")); + else + S86_Print(S86_STR8("\n")); } - -// NOTE: Implementation -// ============================================================================ -S86_Str8 REGISTER_FIELD_ENCODING[2][8]; -S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod, uint8_t w, S86_SegmentRegisterType seg_reg) +void S86_DecodeEffectiveAddr(S86_Opcode *opcode, S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod, uint8_t w) { // NOTE: Calculate displacement // ========================================================================= @@ -171,63 +276,31 @@ S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, S86_ASSERT(mod == 0b00 || mod == 0b11 /*Mem mode (no displacement)*/); } - S86_EffectiveAddressStr8 result = {0}; - result.displacement = displacement; - + opcode->wide = w; + opcode->displacement = displacement; + opcode->effective_addr = S86_EffectiveAddress_Dest; if (mod == 0b11) { - result.reg_type = S86_RegisterTypeFromWReg(w, rm); - - S86_Str8 register_field = REGISTER_FIELD_ENCODING[w][rm]; - memcpy(result.data + result.size, register_field.data, register_field.size); - result.size += register_field.size; + opcode->dest = S86_MnemonicOpFromWReg(w, rm); } else { // NOTE: Effective address calculation w/ displacement // ========================================================================= - if (seg_reg != S86_SegmentRegisterType_Invalid) { - result.seg_reg_type = seg_reg; - S86_Str8 seg_reg_str8 = S86_SegmentRegisterStr8(seg_reg); - memcpy(result.data + result.size, seg_reg_str8.data, seg_reg_str8.size); - result.size += seg_reg_str8.size; - result.data[result.size++] = ':'; - } - - result.has_displacement = true; - result.data[result.size++] = '['; + opcode->effective_addr_loads_mem = true; if (direct_address) { - result.reg_type = S86_RegisterType_DirectAddress; - result.size += snprintf(result.data + result.size, - sizeof(result.data) - result.size, - "%s%d", - displacement >= 0 ? "" : "-", displacement >= 0 ? displacement : -displacement); + opcode->dest = S86_MnemonicOp_DirectAddress; } else { - S86_Str8 base_calc = {0}; switch (rm) { - case 0b000: base_calc = S86_STR8("bx + si"); result.reg_type = S86_RegisterType_BX_SI; break; - case 0b001: base_calc = S86_STR8("bx + di"); result.reg_type = S86_RegisterType_BX_DI; break; - case 0b010: base_calc = S86_STR8("bp + si"); result.reg_type = S86_RegisterType_BP_SI; break; - case 0b011: base_calc = S86_STR8("bp + di"); result.reg_type = S86_RegisterType_BP_DI; break; - case 0b100: base_calc = S86_STR8("si"); result.reg_type = S86_RegisterType_SI; break; - case 0b101: base_calc = S86_STR8("di"); result.reg_type = S86_RegisterType_DI; break; - case 0b110: base_calc = S86_STR8("bp"); result.reg_type = S86_RegisterType_BP; break; - case 0b111: base_calc = S86_STR8("bx"); result.reg_type = S86_RegisterType_BX; break; + case 0b000: opcode->dest = S86_MnemonicOp_BX_SI; break; + case 0b001: opcode->dest = S86_MnemonicOp_BX_DI; break; + case 0b010: opcode->dest = S86_MnemonicOp_BP_SI; break; + case 0b011: opcode->dest = S86_MnemonicOp_BP_DI; break; + case 0b100: opcode->dest = S86_MnemonicOp_SI; break; + case 0b101: opcode->dest = S86_MnemonicOp_DI; break; + case 0b110: opcode->dest = S86_MnemonicOp_BP; break; + case 0b111: opcode->dest = S86_MnemonicOp_BX; break; default: S86_ASSERT(!"Invalid rm value, must be 3 bits"); break; } - - memcpy(result.data + result.size, base_calc.data, base_calc.size); - result.size += S86_CAST(int)base_calc.size; - - if ((mod == 0b01 || mod == 0b10) && displacement) { - result.size += snprintf(result.data + result.size, - sizeof(result.data) - result.size, - " %c %d", - displacement >= 0 ? '+' : '-', displacement >= 0 ? displacement : -displacement); - } } - result.data[result.size++] = ']'; } - - S86_ASSERT(result.size < S86_ARRAY_UCOUNT(result.data)); - return result; } int main(int argc, char **argv) @@ -248,345 +321,318 @@ int main(int argc, char **argv) // NOTE: Sim8086 // ========================================================================= - // Mapping from a 'reg' encoding to the register name. - REGISTER_FIELD_ENCODING[0b0][0] = S86_STR8("al"); - REGISTER_FIELD_ENCODING[0b0][1] = S86_STR8("cl"); - REGISTER_FIELD_ENCODING[0b0][2] = S86_STR8("dl"); - REGISTER_FIELD_ENCODING[0b0][3] = S86_STR8("bl"); - REGISTER_FIELD_ENCODING[0b0][4] = S86_STR8("ah"); - REGISTER_FIELD_ENCODING[0b0][5] = S86_STR8("ch"); - REGISTER_FIELD_ENCODING[0b0][6] = S86_STR8("dh"); - REGISTER_FIELD_ENCODING[0b0][7] = S86_STR8("bh"); + S86_OpDecode const S86_INSTRUCTIONS[] = { + [S86_OpDecodeType_MOVRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1000'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1100'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVImmediateToReg] = {.op_mask0 = 0b1111'0000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1011'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVMemToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1010'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVAccumToMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1010'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVRegOrMemToSegReg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0010'0000, + .op_bits0 = 0b1000'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, + [S86_OpDecodeType_MOVSegRegToRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0010'0000, + .op_bits0 = 0b1000'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_MOV}, - REGISTER_FIELD_ENCODING[0b1][0] = S86_STR8("ax"); - REGISTER_FIELD_ENCODING[0b1][1] = S86_STR8("cx"); - REGISTER_FIELD_ENCODING[0b1][2] = S86_STR8("dx"); - REGISTER_FIELD_ENCODING[0b1][3] = S86_STR8("bx"); - REGISTER_FIELD_ENCODING[0b1][4] = S86_STR8("sp"); - REGISTER_FIELD_ENCODING[0b1][5] = S86_STR8("bp"); - REGISTER_FIELD_ENCODING[0b1][6] = S86_STR8("si"); - REGISTER_FIELD_ENCODING[0b1][7] = S86_STR8("di"); + [S86_OpDecodeType_PUSHRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1111, .op_bits1 = 0b0011'0000, .mnemonic = S86_Mnemonic_PUSH}, + [S86_OpDecodeType_PUSHReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0101'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_PUSH}, + [S86_OpDecodeType_PUSHSegReg] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_PUSH}, - S86_Instruction const S86_INSTRUCTIONS[] = { - [S86_InstructionType_MOVRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1000'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1100'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVImmediateToReg] = {.op_mask0 = 0b1111'0000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1011'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVMemToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1010'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVAccumToMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1010'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVRegOrMemToSegReg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0010'0000, - .op_bits0 = 0b1000'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, - [S86_InstructionType_MOVSegRegToRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0010'0000, - .op_bits0 = 0b1000'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("mov")}, + [S86_OpDecodeType_POPRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_POP}, + [S86_OpDecodeType_POPReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0101'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_POP}, + [S86_OpDecodeType_POPSegReg] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_POP}, - [S86_InstructionType_PUSHRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1111, .op_bits1 = 0b0011'0000, .mnemonic = S86_STR8("push")}, - [S86_InstructionType_PUSHReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0101'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("push")}, - [S86_InstructionType_PUSHSegReg] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("push")}, + [S86_OpDecodeType_XCHGRegOrMemWithReg] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1000'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_XCHG}, + [S86_OpDecodeType_XCHGRegWithAccum] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_XCHG}, - [S86_InstructionType_POPRegOrMem] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("pop")}, - [S86_InstructionType_POPReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0101'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("pop")}, - [S86_InstructionType_POPSegReg] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("pop")}, + [S86_OpDecodeType_INFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_IN}, + [S86_OpDecodeType_INVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_IN}, - [S86_InstructionType_XCHGRegOrMemWithReg] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1000'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xchg")}, - [S86_InstructionType_XCHGRegWithAccum] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xchg")}, + [S86_OpDecodeType_OUTFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_OUT}, + [S86_OpDecodeType_OUTVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_OUT}, - [S86_InstructionType_INFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("in")}, - [S86_InstructionType_INVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("in")}, + [S86_OpDecodeType_XLAT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1101'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_XLAT}, - [S86_InstructionType_OUTFixedPort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("out")}, - [S86_InstructionType_OUTVariablePort] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("out")}, + [S86_OpDecodeType_LEA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1000'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LEA}, + [S86_OpDecodeType_LDS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LDS}, + [S86_OpDecodeType_LES] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LES}, + [S86_OpDecodeType_LAHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LAHF}, + [S86_OpDecodeType_SAHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SAHF}, + [S86_OpDecodeType_PUSHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_PUSHF}, + [S86_OpDecodeType_POPF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_POPF}, - [S86_InstructionType_XLAT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1101'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xlat")}, + [S86_OpDecodeType_ADDRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ADD}, + [S86_OpDecodeType_ADDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ADD}, + [S86_OpDecodeType_ADDImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ADD}, - [S86_InstructionType_LEA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1000'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("lea")}, - [S86_InstructionType_LDS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("lds")}, - [S86_InstructionType_LES] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("les")}, - [S86_InstructionType_LAHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("lahf")}, - [S86_InstructionType_SAHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sahf")}, - [S86_InstructionType_PUSHF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("pushf")}, - [S86_InstructionType_POPF] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("popf")}, + [S86_OpDecodeType_ADCRegOrMemWithRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0001'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ADC}, + [S86_OpDecodeType_ADCImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0001'0000, .mnemonic = S86_Mnemonic_ADC}, + [S86_OpDecodeType_ADCImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0001'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ADC}, - [S86_InstructionType_ADDRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("add")}, - [S86_InstructionType_ADDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("add")}, - [S86_InstructionType_ADDImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("add")}, + [S86_OpDecodeType_INCRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_INC}, + [S86_OpDecodeType_INCReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0100'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_INC}, - [S86_InstructionType_ADCRegOrMemWithRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0001'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("adc")}, - [S86_InstructionType_ADCImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0001'0000, .mnemonic = S86_STR8("adc")}, - [S86_InstructionType_ADCImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0001'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("adc")}, + [S86_OpDecodeType_AAA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_AAA}, + [S86_OpDecodeType_DAA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_DAA}, - [S86_InstructionType_INCRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("inc")}, - [S86_InstructionType_INCReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0100'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("inc")}, + [S86_OpDecodeType_SUBRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SUB}, + [S86_OpDecodeType_SUBImmediateFromRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0010'1000, .mnemonic = S86_Mnemonic_SUB}, + [S86_OpDecodeType_SUBImmediateFromAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SUB}, - [S86_InstructionType_AAA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("aaa")}, - [S86_InstructionType_DAA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("daa")}, + [S86_OpDecodeType_SBBRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0001'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SBB}, + [S86_OpDecodeType_SBBImmediateFromRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0001'1000, .mnemonic = S86_Mnemonic_SBB}, + [S86_OpDecodeType_SBBImmediateFromAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0001'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SBB}, - [S86_InstructionType_SUBRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sub")}, - [S86_InstructionType_SUBImmediateFromRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0010'1000, .mnemonic = S86_STR8("sub")}, - [S86_InstructionType_SUBImmediateFromAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sub")}, + [S86_OpDecodeType_DECRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1110, .op_bits1 = 0b0000'1000, .mnemonic = S86_Mnemonic_DEC}, + [S86_OpDecodeType_DECReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0100'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_DEC}, + [S86_OpDecodeType_NEG] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0001'1000, .mnemonic = S86_Mnemonic_NEG}, - [S86_InstructionType_SBBRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0001'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sbb")}, - [S86_InstructionType_SBBImmediateFromRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0001'1000, .mnemonic = S86_STR8("sbb")}, - [S86_InstructionType_SBBImmediateFromAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0001'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sbb")}, + [S86_OpDecodeType_CMPRegOrMemAndReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CMP}, + [S86_OpDecodeType_CMPImmediateWithRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0011'1000, .mnemonic = S86_Mnemonic_CMP}, + [S86_OpDecodeType_CMPImmediateWithAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CMP}, - [S86_InstructionType_DECRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1110, .op_bits1 = 0b0000'1000, .mnemonic = S86_STR8("dec")}, - [S86_InstructionType_DECReg] = {.op_mask0 = 0b1111'1000, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0100'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("dec")}, - [S86_InstructionType_NEG] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0001'1000, .mnemonic = S86_STR8("neg")}, + [S86_OpDecodeType_AAS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_AAS}, + [S86_OpDecodeType_DAS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_DAS}, - [S86_InstructionType_CMPRegOrMemAndReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cmp")}, - [S86_InstructionType_CMPImmediateWithRegOrMem] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0011'1000, .mnemonic = S86_STR8("cmp")}, - [S86_InstructionType_CMPImmediateWithAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cmp")}, + [S86_OpDecodeType_MUL] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0010'0000, .mnemonic = S86_Mnemonic_MUL}, + [S86_OpDecodeType_IMUL] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0010'1000, .mnemonic = S86_Mnemonic_IMUL}, + [S86_OpDecodeType_AAM] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b1111'1111, + .op_bits0 = 0b1101'0100, .op_bits1 = 0b0000'1010, .mnemonic = S86_Mnemonic_AAM}, + [S86_OpDecodeType_DIV] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0011'0000, .mnemonic = S86_Mnemonic_DIV}, + [S86_OpDecodeType_IDIV] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0011'1000, .mnemonic = S86_Mnemonic_IDIV}, + [S86_OpDecodeType_AAD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b1111'1111, + .op_bits0 = 0b1101'0101, .op_bits1 = 0b0000'1010, .mnemonic = S86_Mnemonic_AAD}, + [S86_OpDecodeType_CBW] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CBW}, + [S86_OpDecodeType_CWD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CWD}, - [S86_InstructionType_AAS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("aas")}, - [S86_InstructionType_DAS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("das")}, + [S86_OpDecodeType_NOT] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0001'0000, .mnemonic = S86_Mnemonic_NOT}, + [S86_OpDecodeType_SHL_SAL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0010'0000, .mnemonic = S86_Mnemonic_SHL_SAL}, + [S86_OpDecodeType_SHR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0010'1000, .mnemonic = S86_Mnemonic_SHR}, + [S86_OpDecodeType_SAR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0011'1000, .mnemonic = S86_Mnemonic_SAR}, + [S86_OpDecodeType_ROL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_ROL}, + [S86_OpDecodeType_ROR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0000'1000, .mnemonic = S86_Mnemonic_ROR}, + [S86_OpDecodeType_RCL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0001'0000, .mnemonic = S86_Mnemonic_RCL}, + [S86_OpDecodeType_RCR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1101'0000, .op_bits1 = 0b0001'1000, .mnemonic = S86_Mnemonic_RCR}, - [S86_InstructionType_MUL] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0010'0000, .mnemonic = S86_STR8("mul")}, - [S86_InstructionType_IMUL] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0010'1000, .mnemonic = S86_STR8("imul")}, - [S86_InstructionType_AAM] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b1111'1111, - .op_bits0 = 0b1101'0100, .op_bits1 = 0b0000'1010, .mnemonic = S86_STR8("aam")}, - [S86_InstructionType_DIV] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0011'0000, .mnemonic = S86_STR8("div")}, - [S86_InstructionType_IDIV] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0011'1000, .mnemonic = S86_STR8("idiv")}, - [S86_InstructionType_AAD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b1111'1111, - .op_bits0 = 0b1101'0101, .op_bits1 = 0b0000'1010, .mnemonic = S86_STR8("aad")}, - [S86_InstructionType_CBW] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cbw")}, - [S86_InstructionType_CWD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cwd")}, + [S86_OpDecodeType_ANDRegWithMemToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_AND}, + [S86_OpDecodeType_ANDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0010'0000, .mnemonic = S86_Mnemonic_AND}, + [S86_OpDecodeType_ANDImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_AND}, - [S86_InstructionType_NOT] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0001'0000, .mnemonic = S86_STR8("not")}, - [S86_InstructionType_SHL_SAL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0010'0000, .mnemonic = S86_STR8("shl")}, - [S86_InstructionType_SHR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0010'1000, .mnemonic = S86_STR8("shr")}, - [S86_InstructionType_SAR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0011'1000, .mnemonic = S86_STR8("sar")}, - [S86_InstructionType_ROL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("rol")}, - [S86_InstructionType_ROR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0000'1000, .mnemonic = S86_STR8("ror")}, - [S86_InstructionType_RCL] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0001'0000, .mnemonic = S86_STR8("rcl")}, - [S86_InstructionType_RCR] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1101'0000, .op_bits1 = 0b0001'1000, .mnemonic = S86_STR8("rcr")}, + [S86_OpDecodeType_TESTRegOrMemAndReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1000'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_TEST}, + [S86_OpDecodeType_TESTImmediateAndRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_TEST}, + [S86_OpDecodeType_TESTImmediateAndAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1010'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_TEST}, - [S86_InstructionType_ANDRegWithMemToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("and")}, - [S86_InstructionType_ANDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0010'0000, .mnemonic = S86_STR8("and")}, - [S86_InstructionType_ANDImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("and")}, + [S86_OpDecodeType_ORRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_OR}, + [S86_OpDecodeType_ORImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0000'1000, .mnemonic = S86_Mnemonic_OR}, + [S86_OpDecodeType_ORImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0000'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_OR}, - [S86_InstructionType_TESTRegOrMemAndReg] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1000'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("test")}, - [S86_InstructionType_TESTImmediateAndRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("test")}, - [S86_InstructionType_TESTImmediateAndAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1010'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("test")}, + [S86_OpDecodeType_XORRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_XOR}, + [S86_OpDecodeType_XORImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1000'0000, .op_bits1 = 0b0011'0000, .mnemonic = S86_Mnemonic_XOR}, + [S86_OpDecodeType_XORImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0011'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_XOR}, - [S86_InstructionType_ORRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("or")}, - [S86_InstructionType_ORImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0000'1000, .mnemonic = S86_STR8("or")}, - [S86_InstructionType_ORImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0000'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("or")}, + [S86_OpDecodeType_REP] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_REP}, - [S86_InstructionType_XORRegOrMemAndRegToEither] = {.op_mask0 = 0b1111'1100, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xor")}, - [S86_InstructionType_XORImmediateToRegOrMem] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1000'0000, .op_bits1 = 0b0011'0000, .mnemonic = S86_STR8("xor")}, - [S86_InstructionType_XORImmediateToAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0011'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("xor")}, + [S86_OpDecodeType_CALLDirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CALL}, + [S86_OpDecodeType_CALLIndirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1111, .op_bits1 = 0b0001'0000, .mnemonic = S86_Mnemonic_CALL}, + [S86_OpDecodeType_CALLDirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CALL}, + [S86_OpDecodeType_CALLIndirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1111, .op_bits1 = 0b0001'1000, .mnemonic = S86_Mnemonic_CALL}, - [S86_InstructionType_REP] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("rep")}, + [S86_OpDecodeType_JMPDirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JMP}, + [S86_OpDecodeType_JMPDirectWithinSegShort] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JMP}, + [S86_OpDecodeType_JMPIndirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1111, .op_bits1 = 0b0010'0000, .mnemonic = S86_Mnemonic_JMP}, + [S86_OpDecodeType_JMPDirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JMP}, + [S86_OpDecodeType_JMPIndirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, + .op_bits0 = 0b1111'1111, .op_bits1 = 0b0010'1000, .mnemonic = S86_Mnemonic_JMP}, - [S86_InstructionType_CALLDirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("call")}, - [S86_InstructionType_CALLIndirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1111, .op_bits1 = 0b0001'0000, .mnemonic = S86_STR8("call")}, - [S86_InstructionType_CALLDirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("call")}, - [S86_InstructionType_CALLIndirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1111, .op_bits1 = 0b0001'1000, .mnemonic = S86_STR8("call")}, + [S86_OpDecodeType_RETWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_RET}, + [S86_OpDecodeType_RETWithinSegAddImmediateToSP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_RET}, + [S86_OpDecodeType_RETInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_RET}, + [S86_OpDecodeType_RETInterSegAddImmediateToSP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_RET}, - [S86_InstructionType_JMPDirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jmp")}, - [S86_InstructionType_JMPDirectWithinSegShort] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jmp")}, - [S86_InstructionType_JMPIndirectWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1111, .op_bits1 = 0b0010'0000, .mnemonic = S86_STR8("jmp")}, - [S86_InstructionType_JMPDirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jmp")}, - [S86_InstructionType_JMPIndirectInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0011'1000, - .op_bits0 = 0b1111'1111, .op_bits1 = 0b0010'1000, .mnemonic = S86_STR8("jmp")}, + [S86_OpDecodeType_JE_JZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JE_JZ}, + [S86_OpDecodeType_JL_JNGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JL_JNGE}, + [S86_OpDecodeType_JLE_JNG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JLE_JNG}, + [S86_OpDecodeType_JB_JNAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JB_JNAE}, + [S86_OpDecodeType_JBE_JNA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JBE_JNA}, + [S86_OpDecodeType_JP_JPE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JP_JPE}, + [S86_OpDecodeType_JO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JO}, + [S86_OpDecodeType_JS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JS}, + [S86_OpDecodeType_JNE_JNZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNE_JNZ}, + [S86_OpDecodeType_JNL_JGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNL_JGE}, + [S86_OpDecodeType_JNLE_JG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNLE_JG}, + [S86_OpDecodeType_JNB_JAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNB_JAE}, + [S86_OpDecodeType_JNBE_JA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNBE_JA}, + [S86_OpDecodeType_JNP_JO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNP_JO}, + [S86_OpDecodeType_JNO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'0001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNO}, + [S86_OpDecodeType_JNS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0111'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JNS}, + [S86_OpDecodeType_LOOP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LOOP}, + [S86_OpDecodeType_LOOPZ_LOOPE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LOOPZ_LOOPE}, + [S86_OpDecodeType_LOOPNZ_LOOPNE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LOOPNZ_LOOPNE}, + [S86_OpDecodeType_JCXZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_JCXZ}, - [S86_InstructionType_RETWithinSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ret")}, - [S86_InstructionType_RETWithinSegAddImmediateToSP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ret")}, - [S86_InstructionType_RETInterSeg] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ret")}, - [S86_InstructionType_RETInterSegAddImmediateToSP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ret")}, + [S86_OpDecodeType_INT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_INT}, + [S86_OpDecodeType_INT3] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_INT3}, + [S86_OpDecodeType_INTO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_INTO}, + [S86_OpDecodeType_IRET] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1100'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_IRET}, - [S86_InstructionType_JE_JZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("je")}, - [S86_InstructionType_JL_JNGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jl")}, - [S86_InstructionType_JLE_JNG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jle")}, - [S86_InstructionType_JB_JNAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jb")}, - [S86_InstructionType_JBE_JNA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jbe")}, - [S86_InstructionType_JP_JPE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jp")}, - [S86_InstructionType_JO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jo")}, - [S86_InstructionType_JS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("js")}, - [S86_InstructionType_JNE_JNZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnz")}, - [S86_InstructionType_JNL_JGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnl")}, - [S86_InstructionType_JNLE_JG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jg")}, - [S86_InstructionType_JNB_JAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnb")}, - [S86_InstructionType_JNBE_JA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ja")}, - [S86_InstructionType_JNP_JO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnp")}, - [S86_InstructionType_JNO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jno")}, - [S86_InstructionType_JNS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jns")}, - [S86_InstructionType_LOOP] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("loop")}, - [S86_InstructionType_LOOPZ_LOOPE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("loopz")}, - [S86_InstructionType_LOOPNZ_LOOPNE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("loopnz")}, - [S86_InstructionType_JCXZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jcxz")}, + [S86_OpDecodeType_CLC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CLC}, + [S86_OpDecodeType_CMC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CMC}, + [S86_OpDecodeType_STC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_STC}, + [S86_OpDecodeType_CLD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CLD}, + [S86_OpDecodeType_STD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_STD}, + [S86_OpDecodeType_CLI] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_CLI}, + [S86_OpDecodeType_STI] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_STI}, + [S86_OpDecodeType_HLT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_HLT}, + [S86_OpDecodeType_WAIT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1001'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_WAIT}, - [S86_InstructionType_INT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("int")}, - [S86_InstructionType_INT3] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("int3")}, - [S86_InstructionType_INTO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("into")}, - [S86_InstructionType_IRET] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1100'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("iret")}, + [S86_OpDecodeType_LOCK] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1111'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_LOCK}, - [S86_InstructionType_CLC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("clc")}, - [S86_InstructionType_CMC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cmc")}, - [S86_InstructionType_STC] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("stc")}, - [S86_InstructionType_CLD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cld")}, - [S86_InstructionType_STD] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("std")}, - [S86_InstructionType_CLI] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1010, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cli")}, - [S86_InstructionType_STI] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("sti")}, - [S86_InstructionType_HLT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("hlt")}, - [S86_InstructionType_WAIT] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1001'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("wait")}, - - [S86_InstructionType_LOCK] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1111'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("lock")}, - - [S86_InstructionType_SEGMENT] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0010'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("")}, - }; - - S86_Str8 SEGMENT_REGISTER_NAME[] = { - [0b00] = S86_STR8("es"), - [0b01] = S86_STR8("cs"), - [0b10] = S86_STR8("ss"), - [0b11] = S86_STR8("ds"), + [S86_OpDecodeType_SEGMENT] = {.op_mask0 = 0b1110'0111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b0010'0110, .op_bits1 = 0b0000'0000, .mnemonic = S86_Mnemonic_SEGMENT}, }; // NOTE: Decode assembly // ========================================================================= S86_PrintLn(S86_STR8("bits 16")); - S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); - S86_SegmentRegisterType seg_reg = {0}; - bool lock_prefix = false; + S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); + S86_MnemonicOp seg_reg = {0}; + bool lock_prefix = false; while (S86_BufferIteratorHasMoreBytes(buffer_it)) { - char op_code_bytes[2] = {0}; size_t op_code_size = 0; op_code_bytes[op_code_size++] = S86_BufferIteratorNextByte(&buffer_it); // NOTE: Match the assembly bytes to the desired instruction // ===================================================================== - S86_InstructionType instruction_type = S86_InstructionType_Count; - S86_Instruction const *instruction = NULL; - for (size_t instruction_index = 0; - instruction_type == S86_InstructionType_Count && instruction_index < S86_ARRAY_UCOUNT(S86_INSTRUCTIONS); - instruction_index++) + S86_OpDecodeType op_decode_type = S86_OpDecodeType_Count; + S86_OpDecode const *op_decode = NULL; + for (size_t op_index = 0; + op_decode_type == S86_OpDecodeType_Count && op_index < S86_ARRAY_UCOUNT(S86_INSTRUCTIONS); + op_index++) { - S86_Instruction const *item = S86_INSTRUCTIONS + instruction_index; + S86_OpDecode const *item = S86_INSTRUCTIONS + op_index; // NOTE: Check first instruction byte // ================================================================= @@ -597,148 +643,148 @@ int main(int argc, char **argv) // ================================================================= // If the matched instruction has a bit mask for the 2nd byte, this // is a multi-byte instruction. Check if the 2nd byte checks out. - bool instruction_matched = true; + bool op_match = true; if (item->op_mask1) { // TODO: This assumes the iterator is valid uint8_t op_byte = S86_BufferIteratorPeekByte(&buffer_it); - instruction_matched = (op_byte & item->op_mask1) == item->op_bits1; - if (instruction_matched) { + op_match = (op_byte & item->op_mask1) == item->op_bits1; + if (op_match) { op_code_bytes[op_code_size++] = op_byte; S86_BufferIteratorNextByte(&buffer_it); } } - if (instruction_matched) { - instruction_type = instruction_index; - instruction = item; + if (op_match) { + op_decode_type = op_index; + op_decode = item; } } // NOTE: Disassemble bytes to assembly mnemonics // ================================================================= S86_ASSERT(op_code_size > 0 && op_code_size <= S86_ARRAY_UCOUNT(op_code_bytes)); - S86_ASSERT(instruction_type != S86_InstructionType_Count && "Unknown instruction"); + S86_ASSERT(op_decode_type != S86_OpDecodeType_Count && "Unknown instruction"); - S86_Print(instruction->mnemonic); - S86_AsmOp asm_op = {0}; - asm_op.lock = lock_prefix; - asm_op.seg_reg = seg_reg; - - switch (instruction_type) { + S86_Opcode opcode = {0}; + opcode.mnemonic = op_decode->mnemonic; + opcode.lock_prefix = lock_prefix; + opcode.seg_reg_prefix = seg_reg; + S86_ASSERT(seg_reg == S86_MnemonicOp_Invalid || (seg_reg >= S86_MnemonicOp_ES && seg_reg <= S86_MnemonicOp_DS)); + switch (op_decode_type) { // NOTE: Instruction Pattern => [0b0000'0000W | 0bAA00'0CCC | DISP-LO | DISP-HI] // Where, W: Optional, AA: mod, CCC: R/M - case S86_InstructionType_JMPIndirectWithinSeg: /*FALLTHRU*/ - case S86_InstructionType_CALLIndirectWithinSeg: /*FALLTHRU*/ - case S86_InstructionType_NOT: /*FALLTHRU*/ - case S86_InstructionType_SHL_SAL: /*FALLTHRU*/ - case S86_InstructionType_SHR: /*FALLTHRU*/ - case S86_InstructionType_SAR: /*FALLTHRU*/ - case S86_InstructionType_ROL: /*FALLTHRU*/ - case S86_InstructionType_ROR: /*FALLTHRU*/ - case S86_InstructionType_RCL: /*FALLTHRU*/ - case S86_InstructionType_RCR: /*FALLTHRU*/ - case S86_InstructionType_MUL: /*FALLTHRU*/ - case S86_InstructionType_IMUL: /*FALLTHRU*/ - case S86_InstructionType_DIV: /*FALLTHRU*/ - case S86_InstructionType_IDIV: /*FALLTHRU*/ - case S86_InstructionType_INCRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_DECRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_NEG: /*FALLTHRU*/ - case S86_InstructionType_POPRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_PUSHRegOrMem: { + case S86_OpDecodeType_JMPIndirectWithinSeg: /*FALLTHRU*/ + case S86_OpDecodeType_CALLIndirectWithinSeg: /*FALLTHRU*/ + case S86_OpDecodeType_NOT: /*FALLTHRU*/ + case S86_OpDecodeType_SHL_SAL: /*FALLTHRU*/ + case S86_OpDecodeType_SHR: /*FALLTHRU*/ + case S86_OpDecodeType_SAR: /*FALLTHRU*/ + case S86_OpDecodeType_ROL: /*FALLTHRU*/ + case S86_OpDecodeType_ROR: /*FALLTHRU*/ + case S86_OpDecodeType_RCL: /*FALLTHRU*/ + case S86_OpDecodeType_RCR: /*FALLTHRU*/ + case S86_OpDecodeType_MUL: /*FALLTHRU*/ + case S86_OpDecodeType_IMUL: /*FALLTHRU*/ + case S86_OpDecodeType_DIV: /*FALLTHRU*/ + case S86_OpDecodeType_IDIV: /*FALLTHRU*/ + case S86_OpDecodeType_INCRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_DECRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_NEG: /*FALLTHRU*/ + case S86_OpDecodeType_POPRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_PUSHRegOrMem: { S86_ASSERT(op_code_size == 2); uint8_t mod = (op_code_bytes[1] & 0b1100'0000) >> 6; uint8_t rm = (op_code_bytes[1] & 0b0000'0111) >> 0; S86_ASSERT(mod < 4); S86_ASSERT(rm < 8); uint8_t w = 1; - if (instruction_type == S86_InstructionType_INCRegOrMem || - instruction_type == S86_InstructionType_DECRegOrMem || - instruction_type == S86_InstructionType_NEG || - instruction_type == S86_InstructionType_MUL || - instruction_type == S86_InstructionType_MUL || - instruction_type == S86_InstructionType_IMUL || - instruction_type == S86_InstructionType_DIV || - instruction_type == S86_InstructionType_IDIV || - (instruction_type >= S86_InstructionType_NOT && - instruction_type <= S86_InstructionType_RCR)) { + if (op_decode_type == S86_OpDecodeType_INCRegOrMem || + op_decode_type == S86_OpDecodeType_DECRegOrMem || + op_decode_type == S86_OpDecodeType_NEG || + op_decode_type == S86_OpDecodeType_MUL || + op_decode_type == S86_OpDecodeType_MUL || + op_decode_type == S86_OpDecodeType_IMUL || + op_decode_type == S86_OpDecodeType_DIV || + op_decode_type == S86_OpDecodeType_IDIV || + (op_decode_type >= S86_OpDecodeType_NOT && + op_decode_type <= S86_OpDecodeType_RCR)) { w = op_code_bytes[0] & 0b0000'0001; } - S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod, w, seg_reg); - if (effective_address.has_displacement) - S86_PrintFmt(" %s", w ? "word" : "byte"); - S86_PrintFmt(" %.*s", S86_STR8_FMT(effective_address)); + S86_DecodeEffectiveAddr(&opcode, &buffer_it, rm, mod, w); + opcode.wide_prefix = S86_WidePrefix_Dest; - // NOTE: Bit shifts use 'v' to indicate if shift distance should + // NOTE: Bit shifts use 'v' to indicate if shift distance should // come from cl register otherwise bitshift by 1 - if (instruction_type >= S86_InstructionType_SHL_SAL && instruction_type <= S86_InstructionType_RCR) { + if (op_decode_type >= S86_OpDecodeType_SHL_SAL && op_decode_type <= S86_OpDecodeType_RCR) { uint8_t v = (op_code_bytes[0] & 0b0000'0010) >> 1; - S86_PrintFmt(", %s", v ? "cl" : "1"); + if (v) { + opcode.src = S86_MnemonicOp_CL; + } else { + opcode.src = S86_MnemonicOp_Immediate; + opcode.immediate = 1; + } } - - S86_Print(S86_STR8("\n")); } break; // NOTE: Instruction Pattern => [0b0000'0000] // Generally handles instructions with control bits in any position in the first byte - case S86_InstructionType_DECReg: /*FALLTHRU*/ - case S86_InstructionType_INCReg: /*FALLTHRU*/ - case S86_InstructionType_XCHGRegWithAccum: /*FALLTHRU*/ - case S86_InstructionType_PUSHReg: /*FALLTHRU*/ - case S86_InstructionType_POPReg: /*FALLTHRU*/ - case S86_InstructionType_PUSHSegReg: /*FALLTHRU*/ - case S86_InstructionType_POPSegReg: { + case S86_OpDecodeType_DECReg: /*FALLTHRU*/ + case S86_OpDecodeType_INCReg: /*FALLTHRU*/ + case S86_OpDecodeType_XCHGRegWithAccum: /*FALLTHRU*/ + case S86_OpDecodeType_PUSHReg: /*FALLTHRU*/ + case S86_OpDecodeType_POPReg: /*FALLTHRU*/ + case S86_OpDecodeType_PUSHSegReg: /*FALLTHRU*/ + case S86_OpDecodeType_POPSegReg: { S86_ASSERT(op_code_size == 1); - S86_Str8 reg_name = {0}; - if (instruction_type == S86_InstructionType_PUSHReg || - instruction_type == S86_InstructionType_POPReg || - instruction_type == S86_InstructionType_INCReg || - instruction_type == S86_InstructionType_DECReg || - instruction_type == S86_InstructionType_XCHGRegWithAccum) { + if (op_decode_type == S86_OpDecodeType_PUSHReg || + op_decode_type == S86_OpDecodeType_POPReg || + op_decode_type == S86_OpDecodeType_INCReg || + op_decode_type == S86_OpDecodeType_DECReg || + op_decode_type == S86_OpDecodeType_XCHGRegWithAccum) { uint8_t reg = (op_code_bytes[0] & 0b0000'0111) >> 0; - reg_name = REGISTER_FIELD_ENCODING[/*w*/1][reg]; + opcode.dest = S86_MnemonicOpFromWReg(1, reg); } else { - S86_ASSERT(instruction_type == S86_InstructionType_PUSHSegReg || - instruction_type == S86_InstructionType_POPSegReg); + S86_ASSERT(op_decode_type == S86_OpDecodeType_PUSHSegReg || + op_decode_type == S86_OpDecodeType_POPSegReg); uint8_t sr = (op_code_bytes[0] & 0b0001'1000) >> 3; - reg_name = SEGMENT_REGISTER_NAME[sr]; + opcode.dest = S86_MnemonicOpFromSR(sr); } - if (instruction_type == S86_InstructionType_XCHGRegWithAccum) - S86_Print(S86_STR8(" ax,")); - - S86_PrintLnFmt(" %.*s", S86_STR8_FMT(reg_name)); + if (op_decode_type == S86_OpDecodeType_XCHGRegWithAccum) { + opcode.src = opcode.dest; + opcode.dest = S86_MnemonicOp_AX; + } } break; // NOTE: Instruction Pattern => [0b0000'000DW | 0bAABB'BCCC | DISP-LO | DISP-HI | DATA-LO | DATA-HI] // Where, D: optional, W: optional, AA: mod, BBB: reg, CCC: r/m - case S86_InstructionType_ADDRegOrMemToOrFromReg: /*FALLTHRU*/ - case S86_InstructionType_ADCRegOrMemWithRegToEither: /*FALLTHRU*/ - case S86_InstructionType_SUBRegOrMemToOrFromReg: /*FALLTHRU*/ - case S86_InstructionType_SBBRegOrMemAndRegToEither: /*FALLTHRU*/ - case S86_InstructionType_ANDRegWithMemToEither: /*FALLTHRU*/ - case S86_InstructionType_TESTRegOrMemAndReg: /*FALLTHRU*/ - case S86_InstructionType_ORRegOrMemAndRegToEither: /*FALLTHRU*/ - case S86_InstructionType_XORRegOrMemAndRegToEither: /*FALLTHRU*/ - case S86_InstructionType_LEA: /*FALLTHRU*/ - case S86_InstructionType_LDS: /*FALLTHRU*/ - case S86_InstructionType_LES: /*FALLTHRU*/ - case S86_InstructionType_XCHGRegOrMemWithReg: /*FALLTHRU*/ - case S86_InstructionType_CMPRegOrMemAndReg: /*FALLTHRU*/ - case S86_InstructionType_MOVRegOrMemToOrFromReg: { + case S86_OpDecodeType_ADDRegOrMemToOrFromReg: /*FALLTHRU*/ + case S86_OpDecodeType_ADCRegOrMemWithRegToEither: /*FALLTHRU*/ + case S86_OpDecodeType_SUBRegOrMemToOrFromReg: /*FALLTHRU*/ + case S86_OpDecodeType_SBBRegOrMemAndRegToEither: /*FALLTHRU*/ + case S86_OpDecodeType_ANDRegWithMemToEither: /*FALLTHRU*/ + case S86_OpDecodeType_TESTRegOrMemAndReg: /*FALLTHRU*/ + case S86_OpDecodeType_ORRegOrMemAndRegToEither: /*FALLTHRU*/ + case S86_OpDecodeType_XORRegOrMemAndRegToEither: /*FALLTHRU*/ + case S86_OpDecodeType_LEA: /*FALLTHRU*/ + case S86_OpDecodeType_LDS: /*FALLTHRU*/ + case S86_OpDecodeType_LES: /*FALLTHRU*/ + case S86_OpDecodeType_XCHGRegOrMemWithReg: /*FALLTHRU*/ + case S86_OpDecodeType_CMPRegOrMemAndReg: /*FALLTHRU*/ + case S86_OpDecodeType_MOVRegOrMemToOrFromReg: { // NOTE: Instruction does not have opcode bits in the 2nd byte S86_ASSERT(op_code_size == 1); op_code_bytes[op_code_size++] = S86_BufferIteratorNextByte(&buffer_it); uint8_t w = (op_code_bytes[0] & 0b0000'0001) >> 0; uint8_t d = (op_code_bytes[0] & 0b0000'0010) >> 1; - if (instruction_type == S86_InstructionType_XCHGRegOrMemWithReg || - instruction_type == S86_InstructionType_LEA || - instruction_type == S86_InstructionType_LDS || - instruction_type == S86_InstructionType_LES) { + if (op_decode_type == S86_OpDecodeType_XCHGRegOrMemWithReg || + op_decode_type == S86_OpDecodeType_LEA || + op_decode_type == S86_OpDecodeType_LDS || + op_decode_type == S86_OpDecodeType_LES) { d = 1; // Destintation is always the register - if (instruction_type == S86_InstructionType_XCHGRegOrMemWithReg) { + if (op_decode_type == S86_OpDecodeType_XCHGRegOrMemWithReg) { if (lock_prefix) { // NOTE: When we XCHG, NASM complains that the // instruction is not lockable, unless, the memory @@ -762,44 +808,38 @@ int main(int argc, char **argv) S86_ASSERT(reg < 8); S86_ASSERT(rm < 8); - asm_op.wide = w; - asm_op.src = S86_RegisterTypeFromWReg(asm_op.wide, reg); + opcode.wide = w; + opcode.src = S86_MnemonicOpFromWReg(opcode.wide, reg); if (mod == 0b11) { // NOTE: Register-to-register move - asm_op.dest = S86_RegisterTypeFromWReg(asm_op.wide, rm); + opcode.dest = S86_MnemonicOpFromWReg(opcode.wide, rm); } else { // NOTE: Memory mode w/ effective address calculation - S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod, w, seg_reg); - asm_op.displacement = effective_address.displacement; - asm_op.src = S86_RegisterTypeFromWReg(w, reg); - asm_op.dest = effective_address.reg_type; - asm_op.has_displacement = effective_address.has_displacement; - if (d) { - asm_op.effective_addr = S86_EffectiveAddress_Src; - } else { - asm_op.effective_addr = S86_EffectiveAddress_Dest; - } + S86_DecodeEffectiveAddr(&opcode, &buffer_it, rm, mod, w); + opcode.src = S86_MnemonicOpFromWReg(w, reg); + if (d) + opcode.effective_addr = S86_EffectiveAddress_Src; + else + opcode.effective_addr = S86_EffectiveAddress_Dest; } if (d) { - S86_RegisterType tmp = asm_op.src; - asm_op.src = asm_op.dest; - asm_op.dest = tmp; + S86_MnemonicOp tmp = opcode.src; + opcode.src = opcode.dest; + opcode.dest = tmp; } - - S86_PrintAsmOp(asm_op); } break; // NOTE: Instruction Pattern => [0b0000'00SW | 0bAAA00BBB | DISP-LO | DISP-HI | DATA-LO | DATA-HI] // Where S: optional, W: optional, AAA: mod, BBB: rm - case S86_InstructionType_ADDImmediateToRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_ADCImmediateToRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_SUBImmediateFromRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_SBBImmediateFromRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_CMPImmediateWithRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_ANDImmediateToRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_TESTImmediateAndRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_ORImmediateToRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_XORImmediateToRegOrMem: /*FALLTHRU*/ - case S86_InstructionType_MOVImmediateToRegOrMem: { + case S86_OpDecodeType_ADDImmediateToRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_ADCImmediateToRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_SUBImmediateFromRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_SBBImmediateFromRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_CMPImmediateWithRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_ANDImmediateToRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_TESTImmediateAndRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_ORImmediateToRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_XORImmediateToRegOrMem: /*FALLTHRU*/ + case S86_OpDecodeType_MOVImmediateToRegOrMem: { S86_ASSERT(op_code_size == 2); uint8_t w = (op_code_bytes[0] & 0b0000'0001) >> 0; uint8_t s = (op_code_bytes[0] & 0b0000'0010) >> 1; @@ -808,75 +848,65 @@ int main(int argc, char **argv) S86_ASSERT(w < 2); S86_ASSERT(mod < 4); S86_ASSERT(rm < 8); - - S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod, w, seg_reg); - asm_op.wide = w; + S86_DecodeEffectiveAddr(&opcode, &buffer_it, rm, mod, w); // NOTE: Parse data payload // ============================================================= uint16_t data = S86_BufferIteratorNextByte(&buffer_it); if (w) { // 16 bit data - if ((instruction_type == S86_InstructionType_ADDImmediateToRegOrMem || - instruction_type == S86_InstructionType_ADCImmediateToRegOrMem || - instruction_type == S86_InstructionType_SUBImmediateFromRegOrMem || - instruction_type == S86_InstructionType_SBBImmediateFromRegOrMem || - instruction_type == S86_InstructionType_CMPImmediateWithRegOrMem || - instruction_type == S86_InstructionType_ANDImmediateToRegOrMem || - instruction_type == S86_InstructionType_TESTImmediateAndRegOrMem || - instruction_type == S86_InstructionType_ORImmediateToRegOrMem || - instruction_type == S86_InstructionType_XORImmediateToRegOrMem) && s) { + if ((op_decode_type == S86_OpDecodeType_ADDImmediateToRegOrMem || + op_decode_type == S86_OpDecodeType_ADCImmediateToRegOrMem || + op_decode_type == S86_OpDecodeType_SUBImmediateFromRegOrMem || + op_decode_type == S86_OpDecodeType_SBBImmediateFromRegOrMem || + op_decode_type == S86_OpDecodeType_CMPImmediateWithRegOrMem || + op_decode_type == S86_OpDecodeType_ANDImmediateToRegOrMem || + op_decode_type == S86_OpDecodeType_TESTImmediateAndRegOrMem || + op_decode_type == S86_OpDecodeType_ORImmediateToRegOrMem || + op_decode_type == S86_OpDecodeType_XORImmediateToRegOrMem) && s) { // NOTE: Sign extend 8 bit, since we store into a - // int32_t in asm_op this is done for free for us. + // int32_t in opcode this is done for free for us. } else { uint8_t data_hi = S86_BufferIteratorNextByte(&buffer_it); data |= (uint16_t)(data_hi) << 8; } } - if (instruction_type == S86_InstructionType_MOVImmediateToRegOrMem) { + if (op_decode_type == S86_OpDecodeType_MOVImmediateToRegOrMem) { S86_ASSERT(mod != 0b11); // NOTE: Op is IMM->Reg, register-to-register not permitted } - // NOTE: Disassemble - // ========================================================= - asm_op.immediate = data; - asm_op.has_displacement = effective_address.has_displacement; - asm_op.displacement = effective_address.displacement; - asm_op.dest = effective_address.reg_type; - asm_op.effective_addr = S86_EffectiveAddress_Dest; - asm_op.src = S86_RegisterType_Immediate; - - if (instruction_type == S86_InstructionType_MOVImmediateToRegOrMem) - asm_op.wide_prefix = S86_WidePrefix_Src; - else if (effective_address.has_displacement) - asm_op.wide_prefix = S86_WidePrefix_Dest; - S86_PrintAsmOp(asm_op); + opcode.immediate = data; + opcode.src = S86_MnemonicOp_Immediate; + if (op_decode_type == S86_OpDecodeType_MOVImmediateToRegOrMem) + opcode.wide_prefix = S86_WidePrefix_Src; + else if (opcode.effective_addr_loads_mem) + opcode.wide_prefix = S86_WidePrefix_Dest; } break; // NOTE: Instruction Pattern => [0b0000'W00W | DATA-LO | DATA-HI] - case S86_InstructionType_ADDImmediateToAccum: /*FALLTHRU*/ - case S86_InstructionType_ADCImmediateToAccum: /*FALLTHRU*/ - case S86_InstructionType_SUBImmediateFromAccum: /*FALLTHRU*/ - case S86_InstructionType_SBBImmediateFromAccum: /*FALLTHRU*/ - case S86_InstructionType_CMPImmediateWithAccum: /*FALLTHRU*/ - case S86_InstructionType_ANDImmediateToAccum: /*FALLTHRU*/ - case S86_InstructionType_TESTImmediateAndAccum: /*FALLTHRU*/ - case S86_InstructionType_ORImmediateToAccum: /*FALLTHRU*/ - case S86_InstructionType_XORImmediateToAccum: /*FALLTHRU*/ - case S86_InstructionType_MOVImmediateToReg: { + case S86_OpDecodeType_ADDImmediateToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_ADCImmediateToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_SUBImmediateFromAccum: /*FALLTHRU*/ + case S86_OpDecodeType_SBBImmediateFromAccum: /*FALLTHRU*/ + case S86_OpDecodeType_CMPImmediateWithAccum: /*FALLTHRU*/ + case S86_OpDecodeType_ANDImmediateToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_TESTImmediateAndAccum: /*FALLTHRU*/ + case S86_OpDecodeType_ORImmediateToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_XORImmediateToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_MOVImmediateToReg: { // NOTE: Parse opcode control bits // ============================================================= S86_ASSERT(op_code_size == 1); uint8_t w = 0; - if (instruction_type == S86_InstructionType_ADDImmediateToAccum || - instruction_type == S86_InstructionType_ADCImmediateToAccum || - instruction_type == S86_InstructionType_SUBImmediateFromAccum || - instruction_type == S86_InstructionType_SBBImmediateFromAccum || - instruction_type == S86_InstructionType_CMPImmediateWithAccum || - instruction_type == S86_InstructionType_ANDImmediateToAccum || - instruction_type == S86_InstructionType_TESTImmediateAndAccum || - instruction_type == S86_InstructionType_ORImmediateToAccum || - instruction_type == S86_InstructionType_XORImmediateToAccum) { + if (op_decode_type == S86_OpDecodeType_ADDImmediateToAccum || + op_decode_type == S86_OpDecodeType_ADCImmediateToAccum || + op_decode_type == S86_OpDecodeType_SUBImmediateFromAccum || + op_decode_type == S86_OpDecodeType_SBBImmediateFromAccum || + op_decode_type == S86_OpDecodeType_CMPImmediateWithAccum || + op_decode_type == S86_OpDecodeType_ANDImmediateToAccum || + op_decode_type == S86_OpDecodeType_TESTImmediateAndAccum || + op_decode_type == S86_OpDecodeType_ORImmediateToAccum || + op_decode_type == S86_OpDecodeType_XORImmediateToAccum) { w = (op_code_bytes[0] & 0b0000'0001) >> 0; } else { w = (op_code_bytes[0] & 0b0000'1000) >> 3; @@ -892,161 +922,158 @@ int main(int argc, char **argv) // NOTE: Disassemble // ============================================================= - asm_op.effective_addr = S86_EffectiveAddress_Dest; - asm_op.src = S86_RegisterType_Immediate; - asm_op.wide = w; - asm_op.src = S86_RegisterType_Immediate; - asm_op.immediate = data; - if (instruction_type == S86_InstructionType_MOVImmediateToReg) { + opcode.effective_addr = S86_EffectiveAddress_Dest; + opcode.src = S86_MnemonicOp_Immediate; + opcode.wide = w; + opcode.src = S86_MnemonicOp_Immediate; + opcode.immediate = data; + if (op_decode_type == S86_OpDecodeType_MOVImmediateToReg) { uint8_t reg = (op_code_bytes[0] & 0b0000'0111) >> 0; - asm_op.dest = S86_RegisterTypeFromWReg(w, reg); + opcode.dest = S86_MnemonicOpFromWReg(w, reg); } else { - asm_op.dest = asm_op.wide ? S86_RegisterType_AX : S86_RegisterType_AL; + opcode.dest = opcode.wide ? S86_MnemonicOp_AX : S86_MnemonicOp_AL; } - S86_PrintAsmOp(asm_op); } break; // NOTE: Instruction Pattern => [0b0000'000W | DATA-LO] - case S86_InstructionType_INFixedPort: /*FALLTHRU*/ - case S86_InstructionType_INVariablePort: /*FALLTHRU*/ - case S86_InstructionType_OUTFixedPort: /*FALLTHRU*/ - case S86_InstructionType_OUTVariablePort: { + case S86_OpDecodeType_INFixedPort: /*FALLTHRU*/ + case S86_OpDecodeType_INVariablePort: /*FALLTHRU*/ + case S86_OpDecodeType_OUTFixedPort: /*FALLTHRU*/ + case S86_OpDecodeType_OUTVariablePort: { S86_ASSERT(op_code_size == 1); - asm_op.wide = (op_code_bytes[0] & 0b0000'0001) >> 0; - asm_op.dest = asm_op.wide ? S86_RegisterType_AX : S86_RegisterType_AL; - if (instruction_type == S86_InstructionType_INFixedPort || - instruction_type == S86_InstructionType_OUTFixedPort) { - asm_op.src = S86_RegisterType_Immediate; - asm_op.immediate = S86_BufferIteratorNextByte(&buffer_it); + opcode.wide = (op_code_bytes[0] & 0b0000'0001) >> 0; + opcode.dest = opcode.wide ? S86_MnemonicOp_AX : S86_MnemonicOp_AL; + if (op_decode_type == S86_OpDecodeType_INFixedPort || + op_decode_type == S86_OpDecodeType_OUTFixedPort) { + opcode.src = S86_MnemonicOp_Immediate; + opcode.immediate = S86_BufferIteratorNextByte(&buffer_it); } else { - asm_op.src = S86_RegisterType_DX; + opcode.src = S86_MnemonicOp_DX; } - if (instruction_type == S86_InstructionType_OUTFixedPort || - instruction_type == S86_InstructionType_OUTVariablePort) { - S86_RegisterType tmp = asm_op.src; - asm_op.src = asm_op.dest; - asm_op.dest = tmp; + if (op_decode_type == S86_OpDecodeType_OUTFixedPort || + op_decode_type == S86_OpDecodeType_OUTVariablePort) { + S86_MnemonicOp tmp = opcode.src; + opcode.src = opcode.dest; + opcode.dest = tmp; } - - S86_PrintAsmOp(asm_op); } break; - case S86_InstructionType_REP: { + case S86_OpDecodeType_REP: { S86_ASSERT(op_code_size == 1); uint8_t string_op = S86_BufferIteratorNextByte(&buffer_it); uint8_t w_mask = 0b0000'0001; - uint8_t w = string_op & w_mask; - - S86_Str8 string_type = {0}; + opcode.rep_prefix = true; + opcode.wide = string_op & w_mask; switch (string_op & ~w_mask) { - case 0b1010'0100: string_type = S86_STR8("movs"); break; - case 0b1010'0110: string_type = S86_STR8("cmps"); break; - case 0b1010'1110: string_type = S86_STR8("scas"); break; - case 0b1010'1100: string_type = S86_STR8("lods"); break; - case 0b1010'1010: string_type = S86_STR8("stos"); break; + case 0b1010'0100: opcode.dest = S86_MnemonicOp_MOVS; break; + case 0b1010'0110: opcode.dest = S86_MnemonicOp_CMPS; break; + case 0b1010'1110: opcode.dest = S86_MnemonicOp_SCAS; break; + case 0b1010'1100: opcode.dest = S86_MnemonicOp_LODS; break; + case 0b1010'1010: opcode.dest = S86_MnemonicOp_STOS; break; default: S86_ASSERT(!"Unhandled REP string type"); break; } - - S86_PrintLnFmt(" %.*s%c", S86_STR8_FMT(string_type), w ? 'w' : 'b'); } break; // NOTE: Instruction Pattern => [0b0000'0000 | DATA-LO | DATA-HI] - case S86_InstructionType_MOVAccumToMem: /*FALLTHRU*/ - case S86_InstructionType_MOVMemToAccum: /*FALLTHRU*/ - case S86_InstructionType_CALLDirectInterSeg: /*FALLTHRU*/ - case S86_InstructionType_CALLDirectWithinSeg: /*FALLTHRU*/ - case S86_InstructionType_JMPDirectInterSeg: /*FALLTHRU*/ - case S86_InstructionType_RETWithinSegAddImmediateToSP: /*FALLTHRU*/ - case S86_InstructionType_INT: { + case S86_OpDecodeType_MOVAccumToMem: /*FALLTHRU*/ + case S86_OpDecodeType_MOVMemToAccum: /*FALLTHRU*/ + case S86_OpDecodeType_CALLDirectInterSeg: /*FALLTHRU*/ + case S86_OpDecodeType_CALLDirectWithinSeg: /*FALLTHRU*/ + case S86_OpDecodeType_JMPDirectInterSeg: /*FALLTHRU*/ + case S86_OpDecodeType_RETWithinSegAddImmediateToSP: /*FALLTHRU*/ + case S86_OpDecodeType_INT: { S86_ASSERT(op_code_size == 1); uint8_t data_lo = S86_BufferIteratorNextByte(&buffer_it); uint16_t data = data_lo; - if (instruction_type != S86_InstructionType_INT) { + if (op_decode_type != S86_OpDecodeType_INT) { uint8_t data_hi = S86_BufferIteratorNextByte(&buffer_it); data = S86_CAST(uint16_t)data_hi << 8 | (S86_CAST(uint16_t)data_lo); } - if (instruction_type == S86_InstructionType_CALLDirectWithinSeg) { - S86_PrintLnFmt(" [bp - %d]", S86_CAST(int16_t)data); - } else if (instruction_type == S86_InstructionType_RETWithinSegAddImmediateToSP) { - S86_PrintLnFmt(" %d", S86_CAST(int16_t)data); - } else if (instruction_type == S86_InstructionType_CALLDirectInterSeg || - instruction_type == S86_InstructionType_JMPDirectInterSeg) { - uint8_t cs_lo = S86_BufferIteratorNextByte(&buffer_it); - uint8_t cs_hi = S86_BufferIteratorNextByte(&buffer_it); - uint16_t cs = S86_CAST(uint16_t)cs_hi << 8 | (S86_CAST(uint16_t)cs_lo); - S86_PrintLnFmt(" %u:%u", cs, data); - } else if (instruction_type == S86_InstructionType_MOVAccumToMem) { - S86_PrintLnFmt(" [%u], ax", data); - } else if (instruction_type == S86_InstructionType_MOVMemToAccum) { - S86_PrintLnFmt(" ax, [%u]", data); + if (op_decode_type == S86_OpDecodeType_CALLDirectWithinSeg) { + opcode.effective_addr = S86_EffectiveAddress_Dest; + opcode.dest = S86_MnemonicOp_BP; + opcode.displacement = -S86_CAST(int32_t)data; + } else if (op_decode_type == S86_OpDecodeType_RETWithinSegAddImmediateToSP) { + opcode.dest = S86_MnemonicOp_DirectAddress; + opcode.displacement = data; + } else if (op_decode_type == S86_OpDecodeType_CALLDirectInterSeg || + op_decode_type == S86_OpDecodeType_JMPDirectInterSeg) { + uint8_t cs_lo = S86_BufferIteratorNextByte(&buffer_it); + uint8_t cs_hi = S86_BufferIteratorNextByte(&buffer_it); + uint16_t cs = S86_CAST(uint16_t)cs_hi << 8 | (S86_CAST(uint16_t)cs_lo); + opcode.displacement = (uint32_t)cs << 16 | (uint32_t)data << 0; + opcode.dest = S86_MnemonicOp_DirectInterSegment; + } else if (op_decode_type == S86_OpDecodeType_MOVAccumToMem) { + opcode.effective_addr_loads_mem = true; + opcode.effective_addr = S86_EffectiveAddress_Dest; + opcode.dest = S86_MnemonicOp_DirectAddress; + opcode.displacement = data; + opcode.src = S86_MnemonicOp_AX; + } else if (op_decode_type == S86_OpDecodeType_MOVMemToAccum) { + opcode.effective_addr_loads_mem = true; + opcode.effective_addr = S86_EffectiveAddress_Src; + opcode.src = S86_MnemonicOp_DirectAddress; + opcode.displacement = data; + opcode.dest = S86_MnemonicOp_AX; } else { - S86_PrintLnFmt(" %u", data); + opcode.dest = S86_MnemonicOp_Immediate; + opcode.immediate = data; } } break; default: { - if (instruction_type >= S86_InstructionType_JE_JZ && instruction_type <= S86_InstructionType_JCXZ) { + if (op_decode_type >= S86_OpDecodeType_JE_JZ && op_decode_type <= S86_OpDecodeType_JCXZ) { S86_ASSERT(op_code_size == 1); - int8_t jump_offset = S86_CAST(int8_t)S86_BufferIteratorNextByte(&buffer_it); - char sign = 0; - if (jump_offset > 0) { - sign = '+'; - } else { - jump_offset *= -1; - sign = '-'; - } - S86_PrintLnFmt(" $+2%c%d", sign, jump_offset); - } else if (instruction_type == S86_InstructionType_XLAT || - instruction_type == S86_InstructionType_LAHF || - instruction_type == S86_InstructionType_SAHF || - instruction_type == S86_InstructionType_PUSHF || - instruction_type == S86_InstructionType_POPF || - instruction_type == S86_InstructionType_DAA || - instruction_type == S86_InstructionType_AAA || - instruction_type == S86_InstructionType_DAS || - instruction_type == S86_InstructionType_AAS || - instruction_type == S86_InstructionType_AAM || - instruction_type == S86_InstructionType_AAD || - instruction_type == S86_InstructionType_CBW || - instruction_type == S86_InstructionType_CWD || - instruction_type == S86_InstructionType_RETWithinSeg || - instruction_type == S86_InstructionType_INT3 || - instruction_type == S86_InstructionType_INTO || - instruction_type == S86_InstructionType_IRET || - instruction_type == S86_InstructionType_CLC || - instruction_type == S86_InstructionType_CMC || - instruction_type == S86_InstructionType_STC || - instruction_type == S86_InstructionType_CLD || - instruction_type == S86_InstructionType_STD || - instruction_type == S86_InstructionType_CLI || - instruction_type == S86_InstructionType_STI || - instruction_type == S86_InstructionType_HLT || - instruction_type == S86_InstructionType_WAIT) { - // NOTE: Mnemonic instruction only, already printed - S86_Print(S86_STR8("\n")); - } else if (instruction_type == S86_InstructionType_LOCK) { - // NOTE: Mnemonic prefix, no new line as the next instruction - // will be prefixed with this instruction - S86_Print(S86_STR8(" ")); - lock_prefix = true; - } else if (instruction_type == S86_InstructionType_SEGMENT) { + opcode.displacement = S86_CAST(int8_t)S86_BufferIteratorNextByte(&buffer_it); + opcode.dest = S86_MnemonicOp_Jump; + } else if (op_decode_type == S86_OpDecodeType_XLAT || + op_decode_type == S86_OpDecodeType_LAHF || + op_decode_type == S86_OpDecodeType_SAHF || + op_decode_type == S86_OpDecodeType_PUSHF || + op_decode_type == S86_OpDecodeType_POPF || + op_decode_type == S86_OpDecodeType_DAA || + op_decode_type == S86_OpDecodeType_AAA || + op_decode_type == S86_OpDecodeType_DAS || + op_decode_type == S86_OpDecodeType_AAS || + op_decode_type == S86_OpDecodeType_AAM || + op_decode_type == S86_OpDecodeType_AAD || + op_decode_type == S86_OpDecodeType_CBW || + op_decode_type == S86_OpDecodeType_CWD || + op_decode_type == S86_OpDecodeType_RETWithinSeg || + op_decode_type == S86_OpDecodeType_INT3 || + op_decode_type == S86_OpDecodeType_INTO || + op_decode_type == S86_OpDecodeType_IRET || + op_decode_type == S86_OpDecodeType_CLC || + op_decode_type == S86_OpDecodeType_CMC || + op_decode_type == S86_OpDecodeType_STC || + op_decode_type == S86_OpDecodeType_CLD || + op_decode_type == S86_OpDecodeType_STD || + op_decode_type == S86_OpDecodeType_CLI || + op_decode_type == S86_OpDecodeType_STI || + op_decode_type == S86_OpDecodeType_HLT || + op_decode_type == S86_OpDecodeType_WAIT) { + // NOTE: Mnemonic only instruction + } else if (op_decode_type == S86_OpDecodeType_LOCK) { + lock_prefix = true; + opcode.lock_prefix = true; + } else if (op_decode_type == S86_OpDecodeType_SEGMENT) { // NOTE: Mnemonic does not generate any assembly S86_ASSERT(op_code_size == 1); uint8_t sr = (op_code_bytes[0] & 0b0001'1000) >> 3; - seg_reg = S86_SegmentRegisterTypeFromSR(sr); + seg_reg = S86_MnemonicOpFromSR(sr); } else { - S86_Print(S86_STR8("\n")); S86_ASSERT(!"Unhandled instruction"); } } break; } - if (instruction_type != S86_InstructionType_LOCK) + S86_PrintOpcode(opcode); + if (op_decode_type != S86_OpDecodeType_LOCK) lock_prefix = false; - if (instruction_type != S86_InstructionType_SEGMENT) - seg_reg = S86_SegmentRegisterType_Invalid; + if (op_decode_type != S86_OpDecodeType_SEGMENT) + seg_reg = S86_MnemonicOp_Invalid; } } diff --git a/part1/sim8086.h b/part1/sim8086.h index 11aade6..3d139ad 100644 --- a/part1/sim8086.h +++ b/part1/sim8086.h @@ -1,167 +1,255 @@ // NOTE: Sim8086 // ============================================================================ -typedef enum S86_InstructionType { - S86_InstructionType_MOVRegOrMemToOrFromReg, - S86_InstructionType_MOVImmediateToRegOrMem, - S86_InstructionType_MOVImmediateToReg, - S86_InstructionType_MOVMemToAccum, - S86_InstructionType_MOVAccumToMem, - S86_InstructionType_MOVRegOrMemToSegReg, - S86_InstructionType_MOVSegRegToRegOrMem, +typedef enum S86_OpDecodeType { + S86_OpDecodeType_MOVRegOrMemToOrFromReg, + S86_OpDecodeType_MOVImmediateToRegOrMem, + S86_OpDecodeType_MOVImmediateToReg, + S86_OpDecodeType_MOVMemToAccum, + S86_OpDecodeType_MOVAccumToMem, + S86_OpDecodeType_MOVRegOrMemToSegReg, + S86_OpDecodeType_MOVSegRegToRegOrMem, - S86_InstructionType_PUSHRegOrMem, - S86_InstructionType_PUSHReg, - S86_InstructionType_PUSHSegReg, + S86_OpDecodeType_PUSHRegOrMem, + S86_OpDecodeType_PUSHReg, + S86_OpDecodeType_PUSHSegReg, - S86_InstructionType_POPRegOrMem, - S86_InstructionType_POPReg, - S86_InstructionType_POPSegReg, + S86_OpDecodeType_POPRegOrMem, + S86_OpDecodeType_POPReg, + S86_OpDecodeType_POPSegReg, - S86_InstructionType_XCHGRegOrMemWithReg, - S86_InstructionType_XCHGRegWithAccum, + S86_OpDecodeType_XCHGRegOrMemWithReg, + S86_OpDecodeType_XCHGRegWithAccum, - S86_InstructionType_INFixedPort, - S86_InstructionType_INVariablePort, + S86_OpDecodeType_INFixedPort, + S86_OpDecodeType_INVariablePort, - S86_InstructionType_OUTFixedPort, - S86_InstructionType_OUTVariablePort, + S86_OpDecodeType_OUTFixedPort, + S86_OpDecodeType_OUTVariablePort, - S86_InstructionType_XLAT, + S86_OpDecodeType_XLAT, - S86_InstructionType_LEA, - S86_InstructionType_LDS, - S86_InstructionType_LES, - S86_InstructionType_LAHF, - S86_InstructionType_SAHF, - S86_InstructionType_PUSHF, - S86_InstructionType_POPF, + S86_OpDecodeType_LEA, + S86_OpDecodeType_LDS, + S86_OpDecodeType_LES, + S86_OpDecodeType_LAHF, + S86_OpDecodeType_SAHF, + S86_OpDecodeType_PUSHF, + S86_OpDecodeType_POPF, - S86_InstructionType_ADDRegOrMemToOrFromReg, - S86_InstructionType_ADDImmediateToRegOrMem, - S86_InstructionType_ADDImmediateToAccum, + S86_OpDecodeType_ADDRegOrMemToOrFromReg, + S86_OpDecodeType_ADDImmediateToRegOrMem, + S86_OpDecodeType_ADDImmediateToAccum, - S86_InstructionType_ADCRegOrMemWithRegToEither, - S86_InstructionType_ADCImmediateToRegOrMem, - S86_InstructionType_ADCImmediateToAccum, + S86_OpDecodeType_ADCRegOrMemWithRegToEither, + S86_OpDecodeType_ADCImmediateToRegOrMem, + S86_OpDecodeType_ADCImmediateToAccum, - S86_InstructionType_INCRegOrMem, - S86_InstructionType_INCReg, + S86_OpDecodeType_INCRegOrMem, + S86_OpDecodeType_INCReg, - S86_InstructionType_AAA, - S86_InstructionType_DAA, + S86_OpDecodeType_AAA, + S86_OpDecodeType_DAA, - S86_InstructionType_SUBRegOrMemToOrFromReg, - S86_InstructionType_SUBImmediateFromRegOrMem, - S86_InstructionType_SUBImmediateFromAccum, + S86_OpDecodeType_SUBRegOrMemToOrFromReg, + S86_OpDecodeType_SUBImmediateFromRegOrMem, + S86_OpDecodeType_SUBImmediateFromAccum, - S86_InstructionType_SBBRegOrMemAndRegToEither, - S86_InstructionType_SBBImmediateFromRegOrMem, - S86_InstructionType_SBBImmediateFromAccum, + S86_OpDecodeType_SBBRegOrMemAndRegToEither, + S86_OpDecodeType_SBBImmediateFromRegOrMem, + S86_OpDecodeType_SBBImmediateFromAccum, - S86_InstructionType_DECRegOrMem, - S86_InstructionType_DECReg, - S86_InstructionType_NEG, + S86_OpDecodeType_DECRegOrMem, + S86_OpDecodeType_DECReg, + S86_OpDecodeType_NEG, - S86_InstructionType_CMPRegOrMemAndReg, - S86_InstructionType_CMPImmediateWithRegOrMem, - S86_InstructionType_CMPImmediateWithAccum, + S86_OpDecodeType_CMPRegOrMemAndReg, + S86_OpDecodeType_CMPImmediateWithRegOrMem, + S86_OpDecodeType_CMPImmediateWithAccum, - S86_InstructionType_AAS, - S86_InstructionType_DAS, + S86_OpDecodeType_AAS, + S86_OpDecodeType_DAS, - S86_InstructionType_MUL, - S86_InstructionType_IMUL, - S86_InstructionType_AAM, - S86_InstructionType_DIV, - S86_InstructionType_IDIV, - S86_InstructionType_AAD, - S86_InstructionType_CBW, - S86_InstructionType_CWD, + S86_OpDecodeType_MUL, + S86_OpDecodeType_IMUL, + S86_OpDecodeType_AAM, + S86_OpDecodeType_DIV, + S86_OpDecodeType_IDIV, + S86_OpDecodeType_AAD, + S86_OpDecodeType_CBW, + S86_OpDecodeType_CWD, - S86_InstructionType_NOT, - S86_InstructionType_SHL_SAL, - S86_InstructionType_SHR, - S86_InstructionType_SAR, - S86_InstructionType_ROL, - S86_InstructionType_ROR, - S86_InstructionType_RCL, - S86_InstructionType_RCR, + S86_OpDecodeType_NOT, + S86_OpDecodeType_SHL_SAL, + S86_OpDecodeType_SHR, + S86_OpDecodeType_SAR, + S86_OpDecodeType_ROL, + S86_OpDecodeType_ROR, + S86_OpDecodeType_RCL, + S86_OpDecodeType_RCR, - S86_InstructionType_ANDRegWithMemToEither, - S86_InstructionType_ANDImmediateToRegOrMem, - S86_InstructionType_ANDImmediateToAccum, + S86_OpDecodeType_ANDRegWithMemToEither, + S86_OpDecodeType_ANDImmediateToRegOrMem, + S86_OpDecodeType_ANDImmediateToAccum, - S86_InstructionType_TESTRegOrMemAndReg, - S86_InstructionType_TESTImmediateAndRegOrMem, - S86_InstructionType_TESTImmediateAndAccum, + S86_OpDecodeType_TESTRegOrMemAndReg, + S86_OpDecodeType_TESTImmediateAndRegOrMem, + S86_OpDecodeType_TESTImmediateAndAccum, - S86_InstructionType_ORRegOrMemAndRegToEither, - S86_InstructionType_ORImmediateToRegOrMem, - S86_InstructionType_ORImmediateToAccum, + S86_OpDecodeType_ORRegOrMemAndRegToEither, + S86_OpDecodeType_ORImmediateToRegOrMem, + S86_OpDecodeType_ORImmediateToAccum, - S86_InstructionType_XORRegOrMemAndRegToEither, - S86_InstructionType_XORImmediateToRegOrMem, - S86_InstructionType_XORImmediateToAccum, + S86_OpDecodeType_XORRegOrMemAndRegToEither, + S86_OpDecodeType_XORImmediateToRegOrMem, + S86_OpDecodeType_XORImmediateToAccum, - S86_InstructionType_REP, + S86_OpDecodeType_REP, - S86_InstructionType_CALLDirectWithinSeg, - S86_InstructionType_CALLIndirectWithinSeg, - S86_InstructionType_CALLDirectInterSeg, - S86_InstructionType_CALLIndirectInterSeg, + S86_OpDecodeType_CALLDirectWithinSeg, + S86_OpDecodeType_CALLIndirectWithinSeg, + S86_OpDecodeType_CALLDirectInterSeg, + S86_OpDecodeType_CALLIndirectInterSeg, - S86_InstructionType_JMPDirectWithinSeg, - S86_InstructionType_JMPDirectWithinSegShort, - S86_InstructionType_JMPIndirectWithinSeg, - S86_InstructionType_JMPDirectInterSeg, - S86_InstructionType_JMPIndirectInterSeg, + S86_OpDecodeType_JMPDirectWithinSeg, + S86_OpDecodeType_JMPDirectWithinSegShort, + S86_OpDecodeType_JMPIndirectWithinSeg, + S86_OpDecodeType_JMPDirectInterSeg, + S86_OpDecodeType_JMPIndirectInterSeg, - S86_InstructionType_RETWithinSeg, - S86_InstructionType_RETWithinSegAddImmediateToSP, - S86_InstructionType_RETInterSeg, - S86_InstructionType_RETInterSegAddImmediateToSP, + S86_OpDecodeType_RETWithinSeg, + S86_OpDecodeType_RETWithinSegAddImmediateToSP, + S86_OpDecodeType_RETInterSeg, + S86_OpDecodeType_RETInterSegAddImmediateToSP, - S86_InstructionType_JE_JZ, - S86_InstructionType_JL_JNGE, - S86_InstructionType_JLE_JNG, - S86_InstructionType_JB_JNAE, - S86_InstructionType_JBE_JNA, - S86_InstructionType_JP_JPE, - S86_InstructionType_JO, - S86_InstructionType_JS, - S86_InstructionType_JNE_JNZ, - S86_InstructionType_JNL_JGE, - S86_InstructionType_JNLE_JG, - S86_InstructionType_JNB_JAE, - S86_InstructionType_JNBE_JA, - S86_InstructionType_JNP_JO, - S86_InstructionType_JNO, - S86_InstructionType_JNS, - S86_InstructionType_LOOP, - S86_InstructionType_LOOPZ_LOOPE, - S86_InstructionType_LOOPNZ_LOOPNE, - S86_InstructionType_JCXZ, + S86_OpDecodeType_JE_JZ, + S86_OpDecodeType_JL_JNGE, + S86_OpDecodeType_JLE_JNG, + S86_OpDecodeType_JB_JNAE, + S86_OpDecodeType_JBE_JNA, + S86_OpDecodeType_JP_JPE, + S86_OpDecodeType_JO, + S86_OpDecodeType_JS, + S86_OpDecodeType_JNE_JNZ, + S86_OpDecodeType_JNL_JGE, + S86_OpDecodeType_JNLE_JG, + S86_OpDecodeType_JNB_JAE, + S86_OpDecodeType_JNBE_JA, + S86_OpDecodeType_JNP_JO, + S86_OpDecodeType_JNO, + S86_OpDecodeType_JNS, + S86_OpDecodeType_LOOP, + S86_OpDecodeType_LOOPZ_LOOPE, + S86_OpDecodeType_LOOPNZ_LOOPNE, + S86_OpDecodeType_JCXZ, - S86_InstructionType_INT, - S86_InstructionType_INT3, - S86_InstructionType_INTO, - S86_InstructionType_IRET, + S86_OpDecodeType_INT, + S86_OpDecodeType_INT3, + S86_OpDecodeType_INTO, + S86_OpDecodeType_IRET, - S86_InstructionType_CLC, - S86_InstructionType_CMC, - S86_InstructionType_STC, - S86_InstructionType_CLD, - S86_InstructionType_STD, - S86_InstructionType_CLI, - S86_InstructionType_STI, - S86_InstructionType_HLT, - S86_InstructionType_WAIT, + S86_OpDecodeType_CLC, + S86_OpDecodeType_CMC, + S86_OpDecodeType_STC, + S86_OpDecodeType_CLD, + S86_OpDecodeType_STD, + S86_OpDecodeType_CLI, + S86_OpDecodeType_STI, + S86_OpDecodeType_HLT, + S86_OpDecodeType_WAIT, - S86_InstructionType_LOCK, - S86_InstructionType_SEGMENT, + S86_OpDecodeType_LOCK, + S86_OpDecodeType_SEGMENT, - S86_InstructionType_Count, -} S86_InstructionType; + S86_OpDecodeType_Count, +} S86_OpDecodeType; + +typedef enum S86_Mnemonic { + S86_Mnemonic_MOV, + S86_Mnemonic_PUSH, + S86_Mnemonic_POP, + S86_Mnemonic_XCHG, + S86_Mnemonic_IN, + S86_Mnemonic_OUT, + S86_Mnemonic_XLAT, + S86_Mnemonic_LEA, + S86_Mnemonic_LDS, + S86_Mnemonic_LES, + S86_Mnemonic_LAHF, + S86_Mnemonic_SAHF, + S86_Mnemonic_PUSHF, + S86_Mnemonic_POPF, + S86_Mnemonic_ADD, + S86_Mnemonic_ADC, + S86_Mnemonic_INC, + S86_Mnemonic_AAA, + S86_Mnemonic_DAA, + S86_Mnemonic_SUB, + S86_Mnemonic_SBB, + S86_Mnemonic_DEC, + S86_Mnemonic_NEG, + S86_Mnemonic_CMP, + S86_Mnemonic_AAS, + S86_Mnemonic_DAS, + S86_Mnemonic_MUL, + S86_Mnemonic_IMUL, + S86_Mnemonic_AAM, + S86_Mnemonic_DIV, + S86_Mnemonic_IDIV, + S86_Mnemonic_AAD, + S86_Mnemonic_CBW, + S86_Mnemonic_CWD, + S86_Mnemonic_NOT, + S86_Mnemonic_SHL_SAL, + S86_Mnemonic_SHR, + S86_Mnemonic_SAR, + S86_Mnemonic_ROL, + S86_Mnemonic_ROR, + S86_Mnemonic_RCL, + S86_Mnemonic_RCR, + S86_Mnemonic_AND, + S86_Mnemonic_TEST, + S86_Mnemonic_OR, + S86_Mnemonic_XOR, + S86_Mnemonic_REP, + S86_Mnemonic_CALL, + S86_Mnemonic_JMP, + S86_Mnemonic_RET, + S86_Mnemonic_JE_JZ, + S86_Mnemonic_JL_JNGE, + S86_Mnemonic_JLE_JNG, + S86_Mnemonic_JB_JNAE, + S86_Mnemonic_JBE_JNA, + S86_Mnemonic_JP_JPE, + S86_Mnemonic_JO, + S86_Mnemonic_JS, + S86_Mnemonic_JNE_JNZ, + S86_Mnemonic_JNL_JGE, + S86_Mnemonic_JNLE_JG, + S86_Mnemonic_JNB_JAE, + S86_Mnemonic_JNBE_JA, + S86_Mnemonic_JNP_JO, + S86_Mnemonic_JNO, + S86_Mnemonic_JNS, + S86_Mnemonic_LOOP, + S86_Mnemonic_LOOPZ_LOOPE, + S86_Mnemonic_LOOPNZ_LOOPNE, + S86_Mnemonic_JCXZ, + S86_Mnemonic_INT, + S86_Mnemonic_INT3, + S86_Mnemonic_INTO, + S86_Mnemonic_IRET, + S86_Mnemonic_CLC, + S86_Mnemonic_CMC, + S86_Mnemonic_STC, + S86_Mnemonic_CLD, + S86_Mnemonic_STD, + S86_Mnemonic_CLI, + S86_Mnemonic_STI, + S86_Mnemonic_HLT, + S86_Mnemonic_WAIT, + S86_Mnemonic_LOCK, + S86_Mnemonic_SEGMENT, +} S86_Mnemonic; /// Bit patterns and masks for decoding 8086 assembly. 8086 opcodes can be up /// to 2 bytes long and mixed with instruction specific control bits. These @@ -170,59 +258,56 @@ typedef enum S86_InstructionType { /// /// Instructions that do not have opcode bits in the 2nd byte will have the mask /// set to 0. -typedef struct S86_Instruction { - uint8_t op_mask0; - uint8_t op_bits0; - uint8_t op_mask1; - uint8_t op_bits1; - S86_Str8 mnemonic; -} S86_Instruction; +typedef struct S86_OpDecode { + S86_Mnemonic mnemonic; + uint8_t op_mask0; + uint8_t op_bits0; + uint8_t op_mask1; + uint8_t op_bits1; +} S86_OpDecode; -typedef enum S86_RegisterType { - S86_RegisterType_AL, - S86_RegisterType_CL, - S86_RegisterType_DL, - S86_RegisterType_BL, - S86_RegisterType_AH, - S86_RegisterType_CH, - S86_RegisterType_DH, - S86_RegisterType_BH, +typedef enum S86_MnemonicOp { + S86_MnemonicOp_Invalid, + S86_MnemonicOp_AL, + S86_MnemonicOp_CL, + S86_MnemonicOp_DL, + S86_MnemonicOp_BL, + S86_MnemonicOp_AH, + S86_MnemonicOp_CH, + S86_MnemonicOp_DH, + S86_MnemonicOp_BH, - S86_RegisterType_AX, - S86_RegisterType_CX, - S86_RegisterType_DX, - S86_RegisterType_BX, - S86_RegisterType_SP, - S86_RegisterType_BP, - S86_RegisterType_SI, - S86_RegisterType_DI, + S86_MnemonicOp_AX, + S86_MnemonicOp_CX, + S86_MnemonicOp_DX, + S86_MnemonicOp_BX, + S86_MnemonicOp_SP, + S86_MnemonicOp_BP, + S86_MnemonicOp_SI, + S86_MnemonicOp_DI, - S86_RegisterType_BX_SI, - S86_RegisterType_BX_DI, - S86_RegisterType_BP_SI, - S86_RegisterType_BP_DI, + S86_MnemonicOp_BX_SI, + S86_MnemonicOp_BX_DI, + S86_MnemonicOp_BP_SI, + S86_MnemonicOp_BP_DI, - S86_RegisterType_DirectAddress, - S86_RegisterType_Immediate, -} S86_RegisterType; + S86_MnemonicOp_DirectAddress, + S86_MnemonicOp_Immediate, -typedef enum S86_SegmentRegisterType { - S86_SegmentRegisterType_Invalid, - S86_SegmentRegisterType_ES, - S86_SegmentRegisterType_CS, - S86_SegmentRegisterType_SS, - S86_SegmentRegisterType_DS, - S86_SegmentRegisterType_Count, -} S86_SegmentRegisterType; + S86_MnemonicOp_ES, + S86_MnemonicOp_CS, + S86_MnemonicOp_SS, + S86_MnemonicOp_DS, -typedef struct S86_EffectiveAddressStr8 { - S86_SegmentRegisterType seg_reg_type; - S86_RegisterType reg_type; - int32_t displacement; - char data[32]; - size_t size; - bool has_displacement; -} S86_EffectiveAddressStr8; + S86_MnemonicOp_MOVS, + S86_MnemonicOp_CMPS, + S86_MnemonicOp_SCAS, + S86_MnemonicOp_LODS, + S86_MnemonicOp_STOS, + + S86_MnemonicOp_DirectInterSegment, + S86_MnemonicOp_Jump, +} S86_MnemonicOp; typedef enum S86_EffectiveAddress { S86_EffectiveAddress_None, @@ -236,19 +321,25 @@ typedef enum S86_WidePrefix { S86_WidePrefix_Dest, } S86_WidePrefix; +typedef struct S86_Opcode { + S86_Mnemonic mnemonic; ///< Mnemonic type + S86_EffectiveAddress effective_addr; ///< Src/dest op is an effective address calculation + bool effective_addr_loads_mem; ///< Effective address uses '[]' notation to load address memory + bool lock_prefix; ///< Prefix the opcode with "lock" instruction + bool rep_prefix; ///< Prefix the opcode with "rep" instruction + bool wide; ///< Opcode has the 'w' flag set + S86_WidePrefix wide_prefix; ///< Mnemonic src/dest op requires a 'word' or 'byte' prefix (e.g. ambiguous immediate size) + S86_MnemonicOp src; ///< Source op for the mnemonic + S86_MnemonicOp dest; ///< Destination op for the mnemonic + int32_t displacement; ///< Opcode has displacement/data/offset + int32_t immediate; ///< Immediate value when src/dest op is an immediate + S86_MnemonicOp seg_reg_prefix; ///< Segment register that should prefix the upcoming instruction +} S86_Opcode; -typedef struct S86_AsmOp { - bool effective_addr_wide_prefix; - S86_EffectiveAddress effective_addr; - bool has_displacement; - bool lock; - bool wide; - S86_WidePrefix wide_prefix; - S86_RegisterType src; - S86_RegisterType dest; - int32_t displacement; - int32_t immediate; - S86_SegmentRegisterType seg_reg; -} S86_AsmOp; - -S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod, uint8_t w, S86_SegmentRegisterType seg_reg); +S86_Str8 S86_MnemonicStr8 (S86_Mnemonic type); +S86_MnemonicOp S86_MnemonicOpFromWReg (bool w, uint8_t reg); +S86_MnemonicOp S86_MnemonicOpFromSR (uint8_t sr); +S86_Str8 S86_MnemonicOpStr8 (S86_MnemonicOp type); +void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src); +void S86_PrintOpcode (S86_Opcode opcode); +void S86_DecodeEffectiveAddr (S86_Opcode *opcode, S86_BufferIterator *it, uint8_t rm, uint8_t mod, uint8_t w); diff --git a/project.rdbg b/project.rdbg index 167e1497159f1e474c12cf48caf45f072fbbfc5a..315b3456bc2a3ec6b59897d1ab2142602cf781c9 100644 GIT binary patch delta 92 zcmcb?e~Wj*21b^R8(kS0xi_~n2{VeaFfcH%asNC5!Xkz5SAsCh;C0y!qLnJVr(iAd7qQL$kNpnVmm delta 179 zcmcb`dxL+%21d4x8(kSE=D4s(u`)0KX;v{H&A<6OqcCGA8v_GFZhnf6LJ}{Km0u8_ zoS%{!pHx|rTFiqaP@Gwn$_eBrm8PYo7R6_lfb_9(|2zW1B8Bf)g0OVylfNL$HhChe s!ej?Fmd)189!wwxH%K`n81PU2$m&0N0V@wkeDZx(E=HJ$G*Dy~0C8