Compare commits

...
2 Commits
Author SHA1 Message Date
ed 6cca3fbe8b decoder seems to be working, need to make a serializer next. 2026-09-09 01:50:20 -04:00
ed 5e6e139cc0 x8616_decode_gen_emit now easier to read... 2026-09-08 23:46:35 -04:00
11 changed files with 263 additions and 136 deletions
+44 -26
View File
@@ -33,7 +33,7 @@ typedef Struct_(X8616_DecodePlex) {
U2 dispatch; U2 dispatch;
U1 plan_idx; U1 plan_idx;
X8616_DecodePlan const* plan; X8616_DecodePlan* plan;
U1 opcode; U1 opcode;
U1 post_opcode; U1 post_opcode;
@@ -80,6 +80,23 @@ typedef Struct_(X8616_DecodePlex) {
FI_ U2 x8616_decode_u2(U1_R bytes) { return C_(U2, bytes[0] | u2_(bytes[1] << 8)); } FI_ U2 x8616_decode_u2(U1_R bytes) { return C_(U2, bytes[0] | u2_(bytes[1] << 8)); }
internal X8616_OpcodePrefix
x8616_decode_opcode(X8616_DecodePlan const* plan, U1 opcode)
{
U1 field_mask = 0;
if (plan->flags & x8616_plan_has_d) field_mask |= u1_(1u << plan->d_shift);
if (plan->flags & x8616_plan_has_w) field_mask |= u1_(1u << plan->w_shift);
if (plan->flags & x8616_plan_has_s) field_mask |= u1_(1u << plan->s_shift);
if (plan->flags & x8616_plan_has_v) field_mask |= u1_(1u << plan->v_shift);
if (plan->flags & x8616_plan_has_z) field_mask |= u1_(1u << plan->z_shift);
if (plan->flags & x8616_plan_has_reg) field_mask |= u1_(0b111u << plan->reg_shift);
if (plan->flags & x8616_plan_has_sr) field_mask |= u1_(0b11u << plan->sr_shift);
if (field_mask == 0) return 0;
U1 stem_mask = u1_(~field_mask);
if (stem_mask == 0) return 0;
return C_(X8616_OpcodePrefix, (opcode & stem_mask) >> count_trailing_zeros_u4(stem_mask));
}
internal void internal void
x8616_decode_apply_prefix(X8616_DecodePlex_R plex, X8616_DecodePlan_R plan, U1 opcode) { x8616_decode_apply_prefix(X8616_DecodePlex_R plex, X8616_DecodePlan_R plan, U1 opcode) {
plex->prefixes.count += 1; plex->prefixes.count += 1;
@@ -107,7 +124,7 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
U2 prefix_dispatch = x8616_decode_dispatch[prefix_opcode]; U2 prefix_dispatch = x8616_decode_dispatch[prefix_opcode];
if (prefix_dispatch == false || (prefix_dispatch & X8616_DECODE_AUX_BIT)) break; if (prefix_dispatch == false || (prefix_dispatch & X8616_DECODE_AUX_BIT)) break;
X8616_DecodePlan const* prefix_plan = x8616_decode_plans + prefix_dispatch; X8616_DecodePlan_R prefix_plan = x8616_decode_plans + prefix_dispatch;
if ((prefix_plan->flags & x8616_plan_is_prefix) == false) break; if ((prefix_plan->flags & x8616_plan_is_prefix) == false) break;
x8616_decode_apply_prefix(plex, prefix_plan, prefix_opcode); x8616_decode_apply_prefix(plex, prefix_plan, prefix_opcode);
@@ -228,7 +245,6 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
plex->instruction.prefixes = plex->prefixes; plex->instruction.prefixes = plex->prefixes;
plex->instruction.op = x8616_op_invalid; plex->instruction.op = x8616_op_invalid;
plex->instruction.decode_flags = (plex->encoding_invalid ? x8616_decode_invalid : 0) | (plex->classification_truncated ? x8616_decode_truncated : 0); plex->instruction.decode_flags = (plex->encoding_invalid ? x8616_decode_invalid : 0) | (plex->classification_truncated ? x8616_decode_truncated : 0);
plex->instruction.opcode = plex->opcode;
plex->instruction.size = u1_(prefix_at + invalid_body_size); plex->instruction.size = u1_(prefix_at + invalid_body_size);
plex->instruction.size_required = plex->instruction.size; plex->instruction.size_required = plex->instruction.size;
return plex->instruction.size; return plex->instruction.size;
@@ -303,39 +319,39 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
X8616_DecodedOperand* source = plex->operand_source; X8616_DecodedOperand* source = plex->operand_source;
source[x8616_operand_reg_modrm].flags = x8616_decoded_operand_register; source[x8616_operand_reg_modrm].flags = x8616_decoded_operand_register;
source[x8616_operand_reg_modrm].width = plex->width; source[x8616_operand_reg_modrm].width = plex->width;
source[x8616_operand_reg_modrm].reg = plex->reg; source[x8616_operand_reg_modrm].reg.r16 = C_(X8616_Reg16, plex->reg);
source[x8616_operand_reg_opcode].flags = x8616_decoded_operand_register; source[x8616_operand_reg_opcode].flags = x8616_decoded_operand_register;
source[x8616_operand_reg_opcode].width = plex->width; source[x8616_operand_reg_opcode].width = plex->width;
source[x8616_operand_reg_opcode].reg = plex->reg_opcode; source[x8616_operand_reg_opcode].reg.r16 = C_(X8616_Reg16, plex->reg_opcode);
source[x8616_operand_segment_modrm].flags = x8616_decoded_operand_segment; source[x8616_operand_segment_modrm].flags = x8616_decoded_operand_segment;
source[x8616_operand_segment_modrm].width = x8616_width_word; source[x8616_operand_segment_modrm].width = x8616_width_word;
source[x8616_operand_segment_modrm].segment = plex->sr_modrm; source[x8616_operand_segment_modrm].segment = C_(X8616_Segment, plex->sr_modrm);
source[x8616_operand_segment_opcode].flags = x8616_decoded_operand_segment; source[x8616_operand_segment_opcode].flags = x8616_decoded_operand_segment;
source[x8616_operand_segment_opcode].width = x8616_width_word; source[x8616_operand_segment_opcode].width = x8616_width_word;
source[x8616_operand_segment_opcode].segment = plex->sr_opcode; source[x8616_operand_segment_opcode].segment = C_(X8616_Segment, plex->sr_opcode);
source[x8616_operand_acc].flags = x8616_decoded_operand_register | x8616_decoded_operand_implicit; source[x8616_operand_acc].flags = x8616_decoded_operand_register | x8616_decoded_operand_implicit;
source[x8616_operand_acc].width = plex->width; source[x8616_operand_acc].width = plex->width;
source[x8616_operand_acc].reg = 0; source[x8616_operand_acc].reg.r16 = x8616_ax;
source[x8616_operand_dx].flags = x8616_decoded_operand_register | x8616_decoded_operand_implicit; source[x8616_operand_dx].flags = x8616_decoded_operand_register | x8616_decoded_operand_implicit;
source[x8616_operand_dx].width = x8616_width_word; source[x8616_operand_dx].width = x8616_width_word;
source[x8616_operand_dx].reg = x8616_dx; source[x8616_operand_dx].reg.r16 = x8616_dx;
source[x8616_operand_rm].width = plex->width; source[x8616_operand_rm].width = plex->width;
if (plex->mod == x8616_mod_reg) { if (plex->mod == x8616_mod_reg) {
source[x8616_operand_rm].flags = x8616_decoded_operand_register; source[x8616_operand_rm].flags = x8616_decoded_operand_register;
source[x8616_operand_rm].reg = plex->rm; source[x8616_operand_rm].reg.r16 = C_(X8616_Reg16, plex->rm);
} }
else { else {
source[x8616_operand_rm].flags = x8616_decoded_operand_memory; source[x8616_operand_rm].flags = x8616_decoded_operand_memory;
source[x8616_operand_rm].mod = plex->mod; source[x8616_operand_rm].mod = C_(X8616_Mod, plex->mod);
source[x8616_operand_rm].ea = plex->rm; source[x8616_operand_rm].ea = C_(X8616_EA, plex->rm);
source[x8616_operand_rm].displacement = plex->displacement; source[x8616_operand_rm].displacement = plex->displacement;
source[x8616_operand_rm].displacement_bytes = plex->displacement_bytes; source[x8616_operand_rm].displacement_bytes = plex->displacement_bytes;
if (plex->direct_memory) { if (plex->direct_memory) {
@@ -382,7 +398,7 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
source[x8616_operand_shift_count].width = x8616_width_byte; source[x8616_operand_shift_count].width = x8616_width_byte;
if (plex->v == x8616_v_cl) { if (plex->v == x8616_v_cl) {
source[x8616_operand_shift_count].flags |= x8616_decoded_operand_register; source[x8616_operand_shift_count].flags |= x8616_decoded_operand_register;
source[x8616_operand_shift_count].reg = x8616_cl; source[x8616_operand_shift_count].reg.r8 = x8616_cl;
} }
else { else {
source[x8616_operand_shift_count].flags |= x8616_decoded_operand_immediate; source[x8616_operand_shift_count].flags |= x8616_decoded_operand_immediate;
@@ -400,10 +416,11 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
plex->instruction.decode_flags = (plex->encoding_invalid ? x8616_decode_invalid : 0) | (plex->classification_truncated ? x8616_decode_truncated : 0); plex->instruction.decode_flags = (plex->encoding_invalid ? x8616_decode_invalid : 0) | (plex->classification_truncated ? x8616_decode_truncated : 0);
plex->instruction.width = plex->width; plex->instruction.width = plex->width;
plex->instruction.prefixes = plex->prefixes; plex->instruction.prefixes = plex->prefixes;
plex->instruction.operand_count = plan->operand_count; plex->instruction.operand_count = plan->operand_count;
plex->instruction.opcode = plex->opcode; plex->instruction.opcode = x8616_decode_opcode(plan, plex->opcode);
plex->instruction.mod_rm = plex->mod_rm; plex->instruction.d = C_(X8616_Direction, (plan->flags & x8616_plan_has_d) ? plex->d : 0);
plex->instruction.has_mod_rm = (plan->flags & x8616_plan_has_modrm) != 0; plex->instruction.w = C_(X8616_Width, (plan->flags & x8616_plan_has_w) ? plex->w : 0);
plex->instruction.has_mod_rm = (plan->flags & x8616_plan_has_modrm) != 0;
U4 total_required = prefix_at + plex->body_required; U4 total_required = prefix_at + plex->body_required;
U4 total_available = plex->source_size; U4 total_available = plex->source_size;
@@ -414,6 +431,7 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
return total_consumed; return total_consumed;
} }
#define x8616_decode_(...) x8616_decode((X8616_DecodeRequest){__VA_ARGS__})
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request) X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request)
{ {
X8616_DecodeInfo result = {0}; X8616_DecodeInfo result = {0};
+34 -28
View File
@@ -12,25 +12,30 @@ enum {
}; };
typedef Enum_(U2, X8616_DecodedOperandFlags) { typedef Enum_(U2, X8616_DecodedOperandFlags) {
x8616_decoded_operand_none = 0b0000000000000000, Bit_(x8616_decoded_operand_none, 0),
x8616_decoded_operand_register = 0b0000000000000001, Bit_(x8616_decoded_operand_register, 1),
x8616_decoded_operand_segment = 0b0000000000000010, Bit_(x8616_decoded_operand_segment, 2),
x8616_decoded_operand_memory = 0b0000000000000100, Bit_(x8616_decoded_operand_memory, 3),
x8616_decoded_operand_immediate = 0b0000000000001000, Bit_(x8616_decoded_operand_immediate, 4),
x8616_decoded_operand_relative = 0b0000000000010000, Bit_(x8616_decoded_operand_relative, 5),
x8616_decoded_operand_far_ptr = 0b0000000000100000, Bit_(x8616_decoded_operand_far_ptr, 6),
x8616_decoded_operand_direct = 0b0000000001000000, Bit_(x8616_decoded_operand_direct, 7),
x8616_decoded_operand_sign_extended = 0b0000000010000000, Bit_(x8616_decoded_operand_sign_extended, 8),
x8616_decoded_operand_implicit = 0b0000000100000000, Bit_(x8616_decoded_operand_implicit, 9),
};
typedef Union_(X8616_DecodedReg) {
X8616_Reg8 r8;
X8616_Reg16 r16;
}; };
typedef Struct_(X8616_DecodedOperand) { typedef Struct_(X8616_DecodedOperand) {
X8616_DecodedOperandFlags flags; X8616_DecodedOperandFlags flags;
X8616_WidthMode width; X8616_WidthMode width;
U1 reg; X8616_DecodedReg reg;
U1 segment; X8616_Segment segment;
U1 mod; X8616_Mod mod;
U1 ea; X8616_EA ea;
S2 displacement; S2 displacement;
U2 address; U2 address;
U2 immediate; U2 immediate;
@@ -64,26 +69,27 @@ typedef Struct_(X8616_DecodedInstruction) {
X8616_DecodedPrefixes prefixes; X8616_DecodedPrefixes prefixes;
X8616_DecodedOperand operands[2]; X8616_DecodedOperand operands[2];
U1 operand_count; U1 operand_count;
U1 opcode; X8616_OpcodePrefix opcode;
U1 mod_rm; X8616_Direction d;
X8616_Width w;
B1 has_mod_rm; B1 has_mod_rm;
U1 size; U1 size;
U1 size_required; U1 size_required;
}; };
typedef Enum_(U2, X8616_DecodePlanFlags) { typedef Enum_(U2, X8616_DecodePlanFlags) {
x8616_plan_none = 0b0000000000000000, Bit_(x8616_plan_none, 0),
x8616_plan_has_modrm = 0b0000000000000001, Bit_(x8616_plan_has_modrm, 1),
x8616_plan_has_post_opcode = 0b0000000000000010, Bit_(x8616_plan_has_post_opcode, 2),
x8616_plan_has_d = 0b0000000000000100, Bit_(x8616_plan_has_d, 3),
x8616_plan_has_w = 0b0000000000001000, Bit_(x8616_plan_has_w, 4),
x8616_plan_has_s = 0b0000000000010000, Bit_(x8616_plan_has_s, 5),
x8616_plan_has_v = 0b0000000000100000, Bit_(x8616_plan_has_v, 6),
x8616_plan_has_z = 0b0000000001000000, Bit_(x8616_plan_has_z, 7),
x8616_plan_has_reg = 0b0000000010000000, Bit_(x8616_plan_has_reg, 8),
x8616_plan_has_sr = 0b0000000100000000, Bit_(x8616_plan_has_sr, 9),
x8616_plan_uses_rm = 0b0000001000000000, Bit_(x8616_plan_uses_rm, 10),
x8616_plan_is_prefix = 0b0000010000000000, Bit_(x8616_plan_is_prefix, 11),
}; };
typedef Enum_(U1, X8616_DecodePayload) { typedef Enum_(U1, X8616_DecodePayload) {
+128 -55
View File
@@ -48,18 +48,16 @@ FI_ B4 x8616_decode_gen_operand_uses_modrm(X8616_Operand operand) {
FI_ B4 x8616_decode_gen_operand_uses_rm(X8616_Operand operand) { return operand == x8616_operand_rm; } FI_ B4 x8616_decode_gen_operand_uses_rm(X8616_Operand operand) { return operand == x8616_operand_rm; }
internal X8616_DecodePayload internal X8616_DecodePayload
x8616_decode_gen_payload_from_operand(X8616_Operand operand) { x8616_decode_gen_payload_from_operand(X8616_Operand operand) { switch (operand) {
switch (operand) { case x8616_operand_imm: return x8616_payload_imm;
case x8616_operand_imm: return x8616_payload_imm; case x8616_operand_imm8: return x8616_payload_imm8;
case x8616_operand_imm8: return x8616_payload_imm8; case x8616_operand_imm16: return x8616_payload_imm16;
case x8616_operand_imm16: return x8616_payload_imm16; case x8616_operand_mem_direct: return x8616_payload_mem_direct;
case x8616_operand_mem_direct: return x8616_payload_mem_direct; case x8616_operand_rel8: return x8616_payload_rel8;
case x8616_operand_rel8: return x8616_payload_rel8; case x8616_operand_rel16: return x8616_payload_rel16;
case x8616_operand_rel16: return x8616_payload_rel16; case x8616_operand_far_ptr: return x8616_payload_far_ptr;
case x8616_operand_far_ptr: return x8616_payload_far_ptr; default: return x8616_payload_none;
default: return x8616_payload_none; }}
}
}
internal X8616_DecodePrefixKind internal X8616_DecodePrefixKind
x8616_decode_gen_prefix_kind(X8616_Encoding const* encoding) { x8616_decode_gen_prefix_kind(X8616_Encoding const* encoding) {
@@ -73,7 +71,7 @@ x8616_decode_gen_prefix_kind(X8616_Encoding const* encoding) {
} }
internal X8616_DecodePlan internal X8616_DecodePlan
x8616_decode_gen_plan(X8616_Encoding const* encoding, U4 encoding_idx, X8616_InfoList* msgs, FArena_R info_scratch) x8616_decode_gen_plan(X8616_Encoding_R encoding, U4 encoding_idx, X8616_InfoList_R msgs, FArena_R info_scratch)
{ {
X8616_DecodePlan plan = {0}; X8616_DecodePlan plan = {0};
plan.op = encoding->op; plan.op = encoding->op;
@@ -142,11 +140,11 @@ x8616_decode_gen_plan(X8616_Encoding const* encoding, U4 encoding_idx, X8616_Inf
return plan; return plan;
} }
FI_ B4 x8616_decode_gen_encoding_matches_opcode(X8616_Encoding const* encoding, U1 opcode) { FI_ B4 x8616_decode_gen_encoding_matches_opcode(X8616_Encoding_R encoding, U1 opcode) {
return (opcode & encoding->opcode.mask) == encoding->opcode.bits; return (opcode & encoding->opcode.mask) == encoding->opcode.bits;
} }
FI_ B4 x8616_decode_gen_plan_matches_second(X8616_DecodePlan const* plan, U1 byte) { FI_ B4 x8616_decode_gen_plan_matches_second(X8616_DecodePlan_R plan, U1 byte) {
if (plan->mod_rm.mask && ((byte & plan->mod_rm.mask) != plan->mod_rm.bits)) return false; if (plan->mod_rm.mask && ((byte & plan->mod_rm.mask) != plan->mod_rm.bits)) return false;
if (plan->post_opcode.mask && ((byte & plan->post_opcode.mask) != plan->post_opcode.bits)) return false; if (plan->post_opcode.mask && ((byte & plan->post_opcode.mask) != plan->post_opcode.bits)) return false;
return true; return true;
@@ -213,7 +211,7 @@ x8616_decode_gen_pass_dispatch(X8616_DecodeGen* gen, FArena_R info_scratch)
} }
internal void internal void
x8616_decode_gen_pass_validate(X8616_DecodeGen* gen, FArena_R info_scratch) x8616_decode_gen_pass_validate(X8616_DecodeGen_R gen, FArena_R info_scratch)
{ {
for (U4 opcode = 0; opcode < 256; ++ opcode) for (U4 opcode = 0; opcode < 256; ++ opcode)
for (U4 second = 0; second < 256; ++ second) for (U4 second = 0; second < 256; ++ second)
@@ -221,10 +219,10 @@ x8616_decode_gen_pass_validate(X8616_DecodeGen* gen, FArena_R info_scratch)
U1 expected = 0; U1 expected = 0;
for (U4 encoding_idx = 0; encoding_idx < X8616_ENCODING_COUNT; ++ encoding_idx) for (U4 encoding_idx = 0; encoding_idx < X8616_ENCODING_COUNT; ++ encoding_idx)
{ {
X8616_Encoding const* encoding = x8616_encodings + encoding_idx; X8616_Encoding_R encoding = x8616_encodings + encoding_idx;
if (x8616_decode_gen_encoding_matches_opcode(encoding, C_(U1, opcode)) == false) continue; if (x8616_decode_gen_encoding_matches_opcode(encoding, C_(U1, opcode)) == false) continue;
X8616_DecodePlan const* plan = gen->plans + encoding_idx + 1; X8616_DecodePlan_R plan = gen->plans + encoding_idx + 1;
if (x8616_decode_gen_plan_matches_second(plan, C_(U1, second)) == false) continue; if (x8616_decode_gen_plan_matches_second(plan, C_(U1, second)) == false) continue;
if (expected) x8616_info_push(info_scratch, & gen->msgs, x8616_info_error if (expected) x8616_info_push(info_scratch, & gen->msgs, x8616_info_error
@@ -295,15 +293,15 @@ typedef Struct_(SMemory) {
}; };
global SMemory smem; global SMemory smem;
I_ void x8616_decode_gen_append_u4(Str8Gen_R out, U4 value, U4 radix, U4 min_digits) { I_ void str8gen_append_u4(Str8Gen_R out, U4 value, U4 radix, U4 min_digits) {
UTF8 buffer[64]; Info_str8_from_u4 info = str8_from_u4_info(value, radix, min_digits, 0); UTF8 buffer[64]; Info_str8_from_u4 info = str8_from_u4_info(value, radix, min_digits, 0);
Str8 text = str8_from_u4_buf(slice_ut_arr(buffer), value, radix, min_digits, 0, info); Str8 text = str8_from_u4_buf(slice_ut_arr(buffer), value, radix, min_digits, 0, info);
str8gen_append_str8(out, text); str8gen_append_str8(out, text);
} }
I_ void x8616_decode_gen_append_hex_u1(Str8Gen_R out, U1 value) { x8616_decode_gen_append_u4(out, value, 16, 2); } I_ void str8gen_append_hex_u1(Str8Gen_R out, U1 value) { str8gen_append_u4(out, value, 16, 2); }
I_ void x8616_decode_gen_append_hex_u2(Str8Gen_R out, U2 value) { x8616_decode_gen_append_u4(out, value, 16, 4); } I_ void str8gen_append_hex_u2(Str8Gen_R out, U2 value) { str8gen_append_u4(out, value, 16, 4); }
I_ void x8616_decode_gen_append_dec (Str8Gen_R out, U4 value) { x8616_decode_gen_append_u4(out, value, 10, 1); } I_ void str8gen_append_dec (Str8Gen_R out, U4 value) { str8gen_append_u4(out, value, 10, 1); }
FI_ Slice scratch_push(U8 len) { return fstack_push_(smem.scratch, len); } FI_ Slice scratch_push(U8 len) { return fstack_push_(smem.scratch, len); }
@@ -316,6 +314,11 @@ I_ Str8 str8_from_u4_opt(U4 num, Opt_str8_from_u4 o) { if (o.radix == 0) {o.radi
#define code_str8(...) slit8(stringify(__VA_ARGS__)) #define code_str8(...) slit8(stringify(__VA_ARGS__))
#define dec(v) str8_from_u4(v, .radix = 10, .min_digits = 1)
#define hex_u1(v) str8_from_u4(v, .radix = 16, .min_digits = 2)
#define hex_u2(v) str8_from_u4(v, .radix = 16, .min_digits = 4)
#define entry(k,v) { ktl_str8_key(k), v }
internal void internal void
x8616_decode_gen_emit_plan(Str8Gen_R out, X8616_DecodePlan_R plan) { defer_rewind(smem.scratch.top) { x8616_decode_gen_emit_plan(Str8Gen_R out, X8616_DecodePlan_R plan) { defer_rewind(smem.scratch.top) {
Str8 template = code_str8( Str8 template = code_str8(
@@ -329,10 +332,6 @@ x8616_decode_gen_emit_plan(Str8Gen_R out, X8616_DecodePlan_R plan) { defer_rewin
},\n },\n
); );
KTL_Slot_Str8 tbl[] = { KTL_Slot_Str8 tbl[] = {
#define dec(value) str8_from_u4(value, .radix = 10, .min_digits = 1)
#define hex_u1(value) str8_from_u4(value, .radix = 16, .min_digits = 2)
#define hex_u2(value) str8_from_u4(value, .radix = 16, .min_digits = 4)
#define entry(key,value) { ktl_str8_key(key), value }
entry("flags", hex_u2(plan->flags)), entry("flags", hex_u2(plan->flags)),
entry("op", hex_u1(plan->op)), entry("op", hex_u1(plan->op)),
entry("encoding_flags", hex_u1(plan->encoding_flags)), entry("encoding_flags", hex_u1(plan->encoding_flags)),
@@ -353,46 +352,120 @@ x8616_decode_gen_emit_plan(Str8Gen_R out, X8616_DecodePlan_R plan) { defer_rewin
entry("mod_rm.mask", hex_u1(plan->mod_rm.mask)), entry("mod_rm.mask", hex_u1(plan->mod_rm.mask)),
entry("post_opcode.bits", hex_u1(plan->post_opcode.bits)), entry("post_opcode.bits", hex_u1(plan->post_opcode.bits)),
entry("post_opcode.mask", hex_u1(plan->post_opcode.mask)), entry("post_opcode.mask", hex_u1(plan->post_opcode.mask)),
#undef dec
#undef hex
#undef entry
}; };
str8gen_append_fmt(out, template, ktl_str8_from_arr(tbl)); str8gen_append_fmt(out, template, ktl_str8_from_arr(tbl));
}} }}
#define gen_fmt(out, tmpl, ...) str8gen_append_fmt((out), (tmpl), ktl_str8_from_arr(((KTL_Slot_Str8[]){ __VA_ARGS__ })))
internal Str8 internal Str8
x8616_decode_gen_emit(Str8Gen_R out, X8616_DecodeGen_R gen) { x8616_decode_gen_emit(Str8Gen_R out, X8616_DecodeGen_R gen)
str8gen_append_str8(out, slit8( {
"// Generated from encoder_table.h. Do not hand-edit.\n" #pragma push_macro("RO_")
"// Plan 0 is the all-zero nil/invalid plan.\n\n" #pragma push_macro("global")
"RO_ global X8616_DecodePlan x8616_decode_plans[")); #undef RO_
x8616_decode_gen_append_dec(out, X8616_ENCODING_COUNT + 1); #undef global
str8gen_append_str8(out, slit8("] =\n{\n")); defer_rewind(smem.scratch.top)
for (U4 idx = 0; idx < X8616_ENCODING_COUNT + 1; ++ idx) x8616_decode_gen_emit_plan(out, gen->plans + idx); {
str8gen_append_str8(out, slit8(
"// Generated from encoder_table.h. Do not hand-edit.\n"
"// Plan 0 is a nil/invalid entry.\n"
"\n"
));
gen_fmt(out, code_str8(RO_ global X8616_DecodePlan x8616_decode_plans[<plan_count>] =\n{\n)
, entry("plan_count", dec(X8616_ENCODING_COUNT + 1))
);
str8gen_append_str8(out, slit8("};\n\nRO_ global U2 x8616_decode_dispatch[256] =\n{\n")); for (U4 idx = 0; idx < X8616_ENCODING_COUNT + 1; ++ idx) { x8616_decode_gen_emit_plan(out, gen->plans + idx); }
for (U4 idx = 0; idx < 256; ++ idx) {
if ((idx & 15) == 0) str8gen_append_str8(out, slit8("\t"));
x8616_decode_gen_append_hex_u2(out, gen->dispatch[idx]);
str8gen_append_str8(out, (idx & 15) == 15 ? slit8(",\n") : slit8(", "));
}
str8gen_append_str8(out, slit8("};\n\nRO_ global U1 x8616_decode_aux[")); str8gen_append_str8(out, code_str8(
x8616_decode_gen_append_dec(out, gen->aux_count); };\n\n
str8gen_append_str8(out, slit8("] =\n{\n")); ));
for (U4 idx = 0; idx < gen->aux_count; ++ idx) {
if ((idx & 15) == 0) str8gen_append_str8(out, slit8("\t")); str8gen_append_str8(out, code_str8(RO_ global U2 x8616_decode_dispatch[256] =\n{\n));
x8616_decode_gen_append_hex_u1(out, gen->aux[idx]); {
str8gen_append_str8(out, (idx & 15) == 15 ? slit8(",\n") : slit8(", ")); Str8 line = code_str8(\t<e0>, <e1>, <e2>, <e3>, <e4>, <e5>, <e6>, <e7>, <e8>, <e9>, <e10>, <e11>, <e12>, <e13>, <e14>, <e15>,\n);
for (U4 idx = 0; idx < 256; idx += 16) defer_rewind(smem.scratch.top) {
U2_R d = gen->dispatch + idx;
gen_fmt(out, line,
entry("e0", hex_u2(d[0])),
entry("e1", hex_u2(d[1])),
entry("e2", hex_u2(d[2])),
entry("e3", hex_u2(d[3])),
entry("e4", hex_u2(d[4])),
entry("e5", hex_u2(d[5])),
entry("e6", hex_u2(d[6])),
entry("e7", hex_u2(d[7])),
entry("e8", hex_u2(d[8])),
entry("e9", hex_u2(d[9])),
entry("e10", hex_u2(d[10])),
entry("e11", hex_u2(d[11])),
entry("e12", hex_u2(d[12])),
entry("e13", hex_u2(d[13])),
entry("e14", hex_u2(d[14])),
entry("e15", hex_u2(d[15]))
);
}
}
str8gen_append_str8(out, code_str8(};\n\n));
gen_fmt(out, code_str8(RO_ global U1 x8616_decode_aux[<aux_count>] =\n{\n)
, entry("aux_count", dec(gen->aux_count))
);
{
Str8 line = code_str8(\t<a0>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6>, <a7>, <a8>, <a9>, <a10>, <a11>, <a12>, <a13>, <a14>, <a15>,\n);
U4 idx = 0;
for (; idx + 16 <= gen->aux_count; idx += 16) defer_rewind(smem.scratch.top) {
U1_R a = gen->aux + idx;
gen_fmt(out, line,
entry("a0", hex_u1(a[0])),
entry("a1", hex_u1(a[1])),
entry("a2", hex_u1(a[2])),
entry("a3", hex_u1(a[3])),
entry("a4", hex_u1(a[4])),
entry("a5", hex_u1(a[5])),
entry("a6", hex_u1(a[6])),
entry("a7", hex_u1(a[7])),
entry("a8", hex_u1(a[8])),
entry("a9", hex_u1(a[9])),
entry("a10", hex_u1(a[10])),
entry("a11", hex_u1(a[11])),
entry("a12", hex_u1(a[12])),
entry("a13", hex_u1(a[13])),
entry("a14", hex_u1(a[14])),
entry("a15", hex_u1(a[15]))
);
}
if (idx < gen->aux_count) {
str8gen_append_str8(out, slit8("\t"));
for (; idx < gen->aux_count; ++ idx) {
str8gen_append_hex_u1(out, gen->aux[idx]); str8gen_append_str8(out, slit8(", "));
}
str8gen_append_str8(out, slit8("\n"));
}
}
str8gen_append_str8(out, code_str8(};\n\n));
gen_fmt(out, code_str8(enum {\n
\tX8616_DECODE_PLAN_COUNT = <plan_count>,\n
\tX8616_DECODE_AUX_COUNT = <aux_count>,
\n};\n
),
entry("plan_count", dec(X8616_ENCODING_COUNT + 1)),
entry("aux_count", dec(gen->aux_count))
);
} }
str8gen_append_str8(out, slit8("};\n\nenum {\n\tX8616_DECODE_PLAN_COUNT = "));
x8616_decode_gen_append_dec(out, X8616_ENCODING_COUNT + 1);
str8gen_append_str8(out, slit8(",\n\tX8616_DECODE_AUX_COUNT = "));
x8616_decode_gen_append_dec(out, gen->aux_count);
str8gen_append_str8(out, slit8(",\n};\n"));
return str8(out->ptr, out->len); return str8(out->ptr, out->len);
#pragma pop_macro("RO_")
#pragma pop_macro("global")
} }
#undef gen_fmt
#undef entry
#undef hex_u2
#undef hex_u1
#undef dec
int int
main(void) { main(void) {
FArena info_scratch = farena_make(slice_ut_arr(smem.info)); FArena info_scratch = farena_make(slice_ut_arr(smem.info));
+3 -3
View File
@@ -1,5 +1,5 @@
// Generated from encoder_table.h. Do not hand-edit. // Generated from encoder_table.h. Do not hand-edit.
// Plan 0 is the all-zero nil/invalid plan. // Plan 0 is a nil/invalid entry.
RO_ global X8616_DecodePlan x8616_decode_plans[132] = RO_ global X8616_DecodePlan x8616_decode_plans[132] =
{ {
@@ -354,6 +354,6 @@ RO_ global U1 x8616_decode_aux[3072] =
}; };
enum { enum {
X8616_DECODE_PLAN_COUNT = 132, X8616_DECODE_PLAN_COUNT = 132,
X8616_DECODE_AUX_COUNT = 3072, X8616_DECODE_AUX_COUNT = 3072,
}; };
+6 -6
View File
@@ -70,7 +70,7 @@ typedef Struct_(X8616_InfoList) {
I_ Str8 x8616_info_template(X8616_InfoCode code) { return code < x8616_info_count ? x8616_info_templates[code] : x8616_info_templates[x8616_info_none]; } I_ Str8 x8616_info_template(X8616_InfoCode code) { return code < x8616_info_count ? x8616_info_templates[code] : x8616_info_templates[x8616_info_none]; }
FI_ void x8616_info_push(FArena_R scratch FI_ void x8616_info_push(FArena_R scratch
, X8616_InfoList_R list , X8616_InfoList_R msgs
, X8616_InfoKind kind , X8616_InfoKind kind
, X8616_InfoCode code , X8616_InfoCode code
, U4 source_offset , U4 source_offset
@@ -79,13 +79,13 @@ FI_ void x8616_info_push(FArena_R scratch
, U4 actual , U4 actual
){ ){
assert(scratch != nullptr); assert(scratch != nullptr);
list->count += 1; msgs->count += 1;
list->error_count += kind == x8616_info_error; msgs->error_count += kind == x8616_info_error;
list->warning_count += kind == x8616_info_warning; msgs->warning_count += kind == x8616_info_warning;
U4 allocation_size = align_pow2(S_(X8616_InfoMsg), MEM_ALIGNMENT_DEFAULT); U4 allocation_size = align_pow2(S_(X8616_InfoMsg), MEM_ALIGNMENT_DEFAULT);
U4 left = scratch->capacity - scratch->used; U4 left = scratch->capacity - scratch->used;
if (allocation_size > left) { ++ list->dropped_count; return; } if (allocation_size > left) { ++ msgs->dropped_count; return; }
X8616_InfoMsg_R msg = farena_push_type(scratch, X8616_InfoMsg); X8616_InfoMsg_R msg = farena_push_type(scratch, X8616_InfoMsg);
// msg[0] = (X8616_InfoMsg){0}; // msg[0] = (X8616_InfoMsg){0};
@@ -96,5 +96,5 @@ FI_ void x8616_info_push(FArena_R scratch
msg->expected = expected; msg->expected = expected;
msg->actual = actual; msg->actual = actual;
msg->text = x8616_info_template(code); msg->text = x8616_info_template(code);
sll_queue_push_n(list->first, list->last, msg, next); sll_queue_push_n(msgs->first, msgs->last, msg, next);
} }
+5 -5
View File
@@ -37,7 +37,7 @@ typedef U1 U1x16 attribute(vector_size(16));
#define x64_u8x4_match(dst, a, b) "vpcmpeqq " x64_r(b) ", " x64_r(a) ", " x64_r(dst) "\n" #define x64_u8x4_match(dst, a, b) "vpcmpeqq " x64_r(b) ", " x64_r(a) ", " x64_r(dst) "\n"
#define x64_u4_from_qword_hits(dst, src) "vmovmskpd " x64_r(src) ", " x64_r(dst) "\n" #define x64_u4_from_qword_hits(dst, src) "vmovmskpd " x64_r(src) ", " x64_r(dst) "\n"
I_ U4 count_trailing_zeros_u4(U4 mask) { FI_ U4 count_trailing_zeros_u4(U4 mask) {
U4 n; U4 n;
asm volatile( asm volatile(
x64_u4_count_trailing_zeros(n, mask) x64_u4_count_trailing_zeros(n, mask)
@@ -47,7 +47,7 @@ I_ U4 count_trailing_zeros_u4(U4 mask) {
return n; return n;
} }
I_ U1x16 splat_u4_u1x16(U4 b4) { FI_ U1x16 splat_u4_u1x16(U4 b4) {
U1x16 v; U1x16 v;
asm volatile( asm volatile(
x64_u1x16_load_mem4 (v, b4) x64_u1x16_load_mem4 (v, b4)
@@ -58,7 +58,7 @@ I_ U1x16 splat_u4_u1x16(U4 b4) {
return v; return v;
} }
I_ U4 mask_eq8_u1x16(U1_R p, U1x16 needle) { FI_ U4 mask_eq8_u1x16(U1_R p, U1x16 needle) {
U1x16 chunk; U1x16 chunk;
U4 mask; U4 mask;
asm volatile( asm volatile(
@@ -72,7 +72,7 @@ I_ U4 mask_eq8_u1x16(U1_R p, U1x16 needle) {
return mask; /* movq zero-fills the high 8 bytes; bits 815 stay 0 */ return mask; /* movq zero-fills the high 8 bytes; bits 815 stay 0 */
} }
I_ U4 mask_eq16_u1x16(U1_R p, U1x16 needle) { FI_ U4 mask_eq16_u1x16(U1_R p, U1x16 needle) {
U1x16 chunk; U1x16 chunk;
U4 mask; U4 mask;
asm volatile( asm volatile(
@@ -105,7 +105,7 @@ I_ U8 find_u1_via_u1x16(U1_R p, U8 len, U1 ch, U1x16 needle) {
return len; /* not found */ return len; /* not found */
} }
I_ U4 find_aos_keys_mask_u8x4(U8_R p0, U8_R p1, U8_R p2, U8_R p3, U8 key) { FI_ U4 find_aos_keys_mask_u8x4(U8_R p0, U8_R p1, U8_R p2, U8_R p3, U8 key) {
U8x2 lo, hi; U8x2 lo, hi;
U8x4 keys, splat, eq; U8x4 keys, splat, eq;
U4 mask; U4 mask;
+4 -3
View File
@@ -10,6 +10,7 @@ Standard: c23
#pragma clang diagnostic ignored "-Wswitch" #pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wuninitialized" #pragma clang diagnostic ignored "-Wuninitialized"
#pragma clang diagnostic ignored "-Wmicrosoft-enum-forward-reference" #pragma clang diagnostic ignored "-Wmicrosoft-enum-forward-reference"
#pragma clang diagnostic ignored "-Wmicrosoft-fixed-enum"
// #pragma comment(lib, "Advapi32.lib") // #pragma comment(lib, "Advapi32.lib")
// #pragma comment(lib, "gdi32.lib") // #pragma comment(lib, "gdi32.lib")
// #pragma comment(lib, "Kernel32.lib") // #pragma comment(lib, "Kernel32.lib")
@@ -122,7 +123,7 @@ Standard: c23
#define Array_expand(type,len) type Array_sym(type, len)[len]; typedef PtrSet_(Array_sym(type, len)) #define Array_expand(type,len) type Array_sym(type, len)[len]; typedef PtrSet_(Array_sym(type, len))
#define Array_(type,len) Array_expand(type,len) #define Array_(type,len) Array_expand(type,len)
#define Bit_(id,b) id = (1 << b), tmpl(id,pos) = b #define Bit_(id,b) id = (1 << b), tmpl(id,pos) = b
#define Enum_(underlying_type, symbol) underlying_type TSet_(symbol); enum symbol #define Enum_(underlying_type, symbol) enum symbol : underlying_type TSet_(symbol); enum symbol : underlying_type
#define Proc_(symbol) symbol #define Proc_(symbol) symbol
#define Relative_(symbol) // Does nothing but annotate that a symbol is associated with another. #define Relative_(symbol) // Does nothing but annotate that a symbol is associated with another.
#define Struct_(symbol) struct symbol TSet_(symbol); struct symbol #define Struct_(symbol) struct symbol TSet_(symbol); struct symbol
@@ -277,8 +278,8 @@ enum {
Bitmask_10 = 0x000003ff, Bitmask_10 = 0x000003ff,
}; };
typedef Enum_(U4,WeekDay){ WeekDay_Sun, WeekDay_Mon, WeekDay_Tue, WeekDay_Wed, WeekDay_Thu, WeekDay_Fri, WeekDay_Sat, WeekDay_Num, }; typedef Enum_(U4, WeekDay) { WeekDay_Sun, WeekDay_Mon, WeekDay_Tue, WeekDay_Wed, WeekDay_Thu, WeekDay_Fri, WeekDay_Sat, WeekDay_Num, };
typedef Enum_(U4,Month) { Month_Jan, Month_Feb, Month_Mar, Month_Apr, Month_May, Month_Jun, Month_Jul, Month_Aug, Month_Sep, Month_Oct, Month_Nov, Month_Dec, Month_Num, }; typedef Enum_(U4, Month) { Month_Jan, Month_Feb, Month_Mar, Month_Apr, Month_May, Month_Jun, Month_Jul, Month_Aug, Month_Sep, Month_Oct, Month_Nov, Month_Dec, Month_Num, };
typedef U8 DenseTime; typedef U8 DenseTime;
+1 -1
View File
@@ -13,7 +13,7 @@
CLANG_OPTIMIZE_DISABLE CLANG_OPTIMIZE_DISABLE
// Most of this referenced from the RAD Debugger codebase. // Most of this referenced from the RAD Debugger codebase.
typedef Enum_(U4,AccessFlags) { typedef Enum_(U4, AccessFlags) {
Bit_(AccessFlag_Read, 0), Bit_(AccessFlag_Read, 0),
Bit_(AccessFlag_Write, 1), Bit_(AccessFlag_Write, 1),
Bit_(AccessFlag_Execute, 2), Bit_(AccessFlag_Execute, 2),
+29 -5
View File
@@ -1,4 +1,5 @@
#include "duffle/dsl.h" #include "duffle/dsl.h"
#include "duffle/asm.h"
#include "duffle/analysis.h" #include "duffle/analysis.h"
#include "duffle/math.h" #include "duffle/math.h"
#include "duffle/memory.h" #include "duffle/memory.h"
@@ -10,6 +11,15 @@
#include "duffle/win32.h" #include "duffle/win32.h"
#include "8086/encoder.h"
#include "8086/encoder_table.h"
#include "8086/info.h"
#include "8086/info_render.h"
#include "8086/decoder.h"
#include "8086/gen/decoder_table.h"
#include "8086/decoder.c"
// #include "8086/decoder.h" // #include "8086/decoder.h"
typedef Struct_(U2_HL) { U1 Low; U1 High; }; typedef Struct_(U2_HL) { U1 Low; U1 High; };
@@ -56,22 +66,23 @@ I_ Str8 binary_as_str8(Slice_U1 data, FArena* str8_mem) { Str8 result = {0};
jret: return result; jret: return result;
} }
enum { enum {
Scratchpad_Len = kilo(1), Scratchpad_Len = kilo(16),
FileRam_Len = kilo(16), FileRam_Len = kilo(16),
}; };
typedef Struct_(SMemory) { typedef Struct_(SMemory) {
U1 Scratchpad [Scratchpad_Len]; U1 Scratchpad [Scratchpad_Len];
U1 FileRam [FileRam_Len]; U1 FileRam [FileRam_Len];
U1 decode_mem[kilo(64)];
}; };
global SMemory smem; global SMemory smem;
#define path_course_content "./course_content/perfaware/" #define path_course_content "./course_content/perfaware/"
#define path_part1 path_course_content "part1/" #define path_part1 path_course_content "part1/"
CLANG_OPTIMIZE_DISABLE typedef Slice_(X8616_DecodedInstruction);
int main() int main()
{ {
FArena scratch = farena_make(slice_ut_arr(smem.Scratchpad)); FArena scratch = farena_make(slice_ut_arr(smem.Scratchpad));
@@ -80,8 +91,21 @@ int main()
Str8 path_listing_0037_single_register_mov = slit8(path_part1 "listing_0037_single_register_mov"); Str8 path_listing_0037_single_register_mov = slit8(path_part1 "listing_0037_single_register_mov");
Str8 path_listing_0037_single_register_mov_asm = slit8(path_part1 "listing_0037_single_register_mov.asm"); Str8 path_listing_0037_single_register_mov_asm = slit8(path_part1 "listing_0037_single_register_mov.asm");
Slice_U1 data = data_from_file_path(& file_arena, path_listing_0037_single_register_mov, & scratch); Slice_U1 data = data_from_file_path(& file_arena, path_listing_0037_single_register_mov, & scratch);
farena_reset(& scratch);
FArena decode_arena = farena_make(slice_ut_arr(smem.decode_mem));
Slice_X8616_DecodedInstruction decoded = farena_push_array(& decode_arena, X8616_DecodedInstruction, data.len);
X8616_DecodeInfo info = x8616_decode_(
.source = data.ptr,
.source_size = data.len,
.instructions = decoded.ptr,
.instruction_capacity = decoded.len,
.info_arena = & decode_arena,
);
assert(info.instruction_count > 0);
// Str8 infO_report = x8616_info_render(slice_ut_arr(smem.Scratchpad), info.msgs.first,);
ms_exit_process(0); ms_exit_process(0);
return 0; return 0;
} }
CLANG_OPTIMIZE_ENABLE
+7 -2
View File
@@ -3,7 +3,12 @@
target: target:
{ {
executable: "build/sim_8086.exe" executable: "build/sim_8086.exe"
working_directory: "" working_directory: "../perfaware"
enabled: 1
label: "Sim 8086" label: "Sim 8086"
enabled: 1
}
target:
{
executable: "build/decoder_table_generator.meta.exe"
working_directory: "../perfaware"
} }
+2 -2
View File
@@ -391,7 +391,7 @@ function build-8086_decoder_table {
dump-disassembly $module_c $exe dump-disassembly $module_c $exe
} }
build-8086_decoder_table # build-8086_decoder_table
function build-part_1 { function build-part_1 {
# The base lib uses subdir-prefixed includes (e.g. "duffle/dsl.h"), # The base lib uses subdir-prefixed includes (e.g. "duffle/dsl.h"),
@@ -418,4 +418,4 @@ function build-part_1 {
dump-disassembly $module_c $exe dump-disassembly $module_c $exe
} }
# build-part_1 build-part_1