3 Commits
Author SHA1 Message Date
ed d3fd791537 working on serializer 2026-09-09 12:09:12 -04:00
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
14 changed files with 921 additions and 258 deletions
+34 -16
View File
@@ -24,7 +24,7 @@ RO_ global U1 x8616_decode_payload_bytes[] = {
}; };
typedef Struct_(X8616_DecodePlex) { typedef Struct_(X8616_DecodePlex) {
U1 const* source; U1* source;
U4 source_size; U4 source_size;
U4 source_offset; U4 source_offset;
@@ -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;
@@ -305,37 +321,37 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
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;
@@ -401,8 +417,9 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
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.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; 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;
@@ -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};
+35 -29
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) {
@@ -136,7 +142,7 @@ enum {
}; };
typedef Struct_(X8616_DecodeRequest) { typedef Struct_(X8616_DecodeRequest) {
U1 const* source; U1* source;
U4 source_size; U4 source_size;
X8616_DecodedInstruction* instructions; X8616_DecodedInstruction* instructions;
-36
View File
@@ -1,36 +0,0 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "duffle/dsl.h"
# include "encoder.h"
# include "decoder.h"
# include "info.h"
#endif
internal void
x8616_decoder_smoke_test(void)
{
U1 bytes[] = {
x8616_mov_r16_i (x8616_ax, 0x1234),
x8616_add_r16_i8s(x8616_ax, -2),
x8616_nop(),
};
X8616_DecodedInstruction instructions[3] = {0};
U1 info_memory[1024] = {0};
FArena info_scratch = farena_make(slice_ut_arr(info_memory));
X8616_DecodeInfo info = x8616_decode((X8616_DecodeRequest){
.source = bytes,
.source_size = S_(bytes),
.instructions = instructions,
.instruction_capacity = Array_len(instructions),
.info_arena = & info_scratch,
});
assert(info.source_consumed == S_(bytes));
assert(info.instruction_count == 3);
assert(info.msgs.error_count == 0);
assert(instructions[0].op == x8616_op_mov);
assert(instructions[1].op == x8616_op_add);
assert(instructions[2].op == x8616_op_xchg); /* 0x90 in the Part 1 table */
}
+121 -47
View File
@@ -48,8 +48,7 @@ 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;
@@ -58,8 +57,7 @@ x8616_decode_gen_payload_from_operand(X8616_Operand operand) {
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,48 +352,123 @@ 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)
{
#pragma push_macro("RO_")
#pragma push_macro("global")
#undef RO_
#undef global
defer_rewind(smem.scratch.top)
{
str8gen_append_str8(out, slit8( str8gen_append_str8(out, slit8(
"// Generated from encoder_table.h. Do not hand-edit.\n" "// Generated from encoder_table.h. Do not hand-edit.\n"
"// Plan 0 is the all-zero nil/invalid plan.\n\n" "// Plan 0 is a nil/invalid entry.\n"
"RO_ global X8616_DecodePlan x8616_decode_plans[")); "#ifdef INTELLISENSE_DIRECTIVES\n"
x8616_decode_gen_append_dec(out, X8616_ENCODING_COUNT + 1); "#\tinclude \"dsl.h\"\n"
str8gen_append_str8(out, slit8("] =\n{\n")); "#endif\n\n"
for (U4 idx = 0; idx < X8616_ENCODING_COUNT + 1; ++ idx) x8616_decode_gen_emit_plan(out, gen->plans + idx); ));
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")
} }
int #undef gen_fmt
main(void) { #undef entry
#undef hex_u2
#undef hex_u1
#undef dec
int main(void) {
FArena info_scratch = farena_make(slice_ut_arr(smem.info)); FArena info_scratch = farena_make(slice_ut_arr(smem.info));
X8616_DecodeGenInfo gen_info = x8616_decode_table_generate(& smem.gen, & info_scratch); X8616_DecodeGenInfo gen_info = x8616_decode_table_generate(& smem.gen, & info_scratch);
if (gen_info.msgs.error_count) { ms_exit_process(1); return 1; } if (gen_info.msgs.error_count) { ms_exit_process(1); return 1; }
+82 -79
View File
@@ -1,103 +1,106 @@
// 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.
#ifdef INTELLISENSE_DIRECTIVES
# include "dsl.h"
#endif
RO_ global X8616_DecodePlan x8616_decode_plans[132] = RO_ global X8616_DecodePlan x8616_decode_plans[132] =
{ {
{ 0x0000, 0x00, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x00, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x02, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x02, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x02, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x02, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0088, 0x02, 0x00, 0x00, {0x03, 0x07}, 2, 1, 0, 0, 3, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0110, 0x02, 0x00, 0x00, {0x03, 0x07}, 2, 1, 0, 0, 3, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x000c, 0x02, 0x00, 0x00, {0x06, 0x0a}, 2, 4, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0018, 0x02, 0x00, 0x00, {0x06, 0x0a}, 2, 4, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0205, 0x02, 0x00, 0x02, {0x01, 0x04}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x20}, {0x00, 0x00}, }, { 0x040a, 0x02, 0x00, 0x02, {0x01, 0x04}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x20}, {0x00, 0x00}, },
{ 0x0201, 0x0b, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x0b, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
{ 0x0080, 0x0b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0100, 0x0b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0100, 0x0b, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0200, 0x0b, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x0c, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x0c, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0080, 0x0c, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0100, 0x0c, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0100, 0x0c, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0200, 0x0c, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x0d, 0x00, 0x00, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0412, 0x0d, 0x00, 0x00, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0080, 0x0d, 0x00, 0x02, {0x06, 0x03}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0100, 0x0d, 0x00, 0x02, {0x06, 0x03}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x0e, 0x00, 0x00, {0x06, 0x08}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x0e, 0x00, 0x00, {0x06, 0x08}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x0e, 0x00, 0x00, {0x06, 0x0e}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x0e, 0x00, 0x00, {0x06, 0x0e}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x0f, 0x00, 0x00, {0x08, 0x06}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x0f, 0x00, 0x00, {0x08, 0x06}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x0f, 0x00, 0x00, {0x0e, 0x06}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x0f, 0x00, 0x00, {0x0e, 0x06}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x10, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x10, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x11, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0402, 0x11, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x12, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0402, 0x12, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x13, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0402, 0x13, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x14, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x14, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x15, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x15, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x16, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x16, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x17, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x17, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x03, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x03, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0219, 0x03, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0432, 0x03, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x03, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x03, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x04, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x04, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x04, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x04, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x04, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x04, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x05, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x05, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0219, 0x05, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, }, { 0x0432, 0x05, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x05, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x05, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x06, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x06, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0219, 0x06, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, }, { 0x0432, 0x06, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x06, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x06, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x07, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x07, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x07, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x07, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x07, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x07, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x08, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x08, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0219, 0x08, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, }, { 0x0432, 0x08, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x08, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x08, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x09, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x09, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x09, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x09, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x09, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x09, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x020d, 0x0a, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x041a, 0x0a, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0219, 0x0a, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, }, { 0x0432, 0x0a, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x0a, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x0a, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x18, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x18, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0080, 0x18, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0100, 0x18, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x19, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x19, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x1a, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x1a, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x1b, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x1b, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
{ 0x0080, 0x1b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0100, 0x1b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x1c, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x1c, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x1f, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x1f, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x20, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x20, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x22, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x22, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x23, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x23, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x27, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x27, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
{ 0x0000, 0x1d, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x1d, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x1e, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x1e, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0002, 0x21, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, }, { 0x0004, 0x21, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, },
{ 0x0002, 0x24, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, }, { 0x0004, 0x24, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, },
{ 0x0000, 0x25, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x25, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x26, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x26, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0229, 0x2b, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x2b, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x2c, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x2c, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x2d, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x2d, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x2e, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x2e, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x28, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x28, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x29, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x29, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
{ 0x0229, 0x2a, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, }, { 0x0452, 0x2a, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
{ 0x0209, 0x2f, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0412, 0x2f, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0209, 0x2f, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, }, { 0x0412, 0x2f, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
{ 0x0008, 0x2f, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x2f, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0440, 0x30, 0x02, 0x00, {0x00, 0x00}, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0880, 0x30, 0x02, 0x00, {0x00, 0x00}, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x31, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x31, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x32, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x32, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x33, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x33, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x34, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x34, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0008, 0x35, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0010, 0x35, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0400, 0x5b, 0x02, 0x00, {0x00, 0x00}, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0800, 0x5b, 0x02, 0x00, {0x00, 0x00}, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0500, 0x5c, 0x02, 0x00, {0x00, 0x00}, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0a00, 0x5c, 0x02, 0x00, {0x00, 0x00}, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x36, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x36, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x36, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x36, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
{ 0x0000, 0x36, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x36, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x36, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x36, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
{ 0x0000, 0x37, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x37, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x37, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x37, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x37, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x37, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
{ 0x0000, 0x37, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x37, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0201, 0x37, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, }, { 0x0402, 0x37, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
{ 0x0000, 0x38, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x38, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x38, 0x00, 0x00, {0x09, 0x00}, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x38, 0x00, 0x00, {0x09, 0x00}, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x39, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, }, { 0x0000, 0x39, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
+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);
} }
+522
View File
@@ -0,0 +1,522 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "serializer.h"
#endif
enum {
X8616_SERIALIZE_HEADER_LEN = 9,
};
RO_ global Str8 x8616_serialize_header = slit8("bits 16\n\n");
RO_ global Str8 x8616_serialize_mnemonic[] = {
[x8616_op_invalid] = slit8(""),
[x8616_op_nop] = slit8("nop"),
[x8616_op_mov] = slit8("mov"),
[x8616_op_add] = slit8("add"),
[x8616_op_or] = slit8("or"),
[x8616_op_adc] = slit8("adc"),
[x8616_op_sbb] = slit8("sbb"),
[x8616_op_and] = slit8("and"),
[x8616_op_sub] = slit8("sub"),
[x8616_op_xor] = slit8("xor"),
[x8616_op_cmp] = slit8("cmp"),
[x8616_op_push] = slit8("push"),
[x8616_op_pop] = slit8("pop"),
[x8616_op_xchg] = slit8("xchg"),
[x8616_op_in] = slit8("in"),
[x8616_op_out] = slit8("out"),
[x8616_op_xlat] = slit8("xlat"),
[x8616_op_lea] = slit8("lea"),
[x8616_op_lds] = slit8("lds"),
[x8616_op_les] = slit8("les"),
[x8616_op_lahf] = slit8("lahf"),
[x8616_op_sahf] = slit8("sahf"),
[x8616_op_pushf] = slit8("pushf"),
[x8616_op_popf] = slit8("popf"),
[x8616_op_inc] = slit8("inc"),
[x8616_op_aaa] = slit8("aaa"),
[x8616_op_daa] = slit8("daa"),
[x8616_op_dec] = slit8("dec"),
[x8616_op_neg] = slit8("neg"),
[x8616_op_aas] = slit8("aas"),
[x8616_op_das] = slit8("das"),
[x8616_op_mul] = slit8("mul"),
[x8616_op_imul] = slit8("imul"),
[x8616_op_aam] = slit8("aam"),
[x8616_op_div] = slit8("div"),
[x8616_op_idiv] = slit8("idiv"),
[x8616_op_aad] = slit8("aad"),
[x8616_op_cbw] = slit8("cbw"),
[x8616_op_cwd] = slit8("cwd"),
[x8616_op_not] = slit8("not"),
[x8616_op_shl] = slit8("shl"),
[x8616_op_shr] = slit8("shr"),
[x8616_op_sar] = slit8("sar"),
[x8616_op_rol] = slit8("rol"),
[x8616_op_ror] = slit8("ror"),
[x8616_op_rcl] = slit8("rcl"),
[x8616_op_rcr] = slit8("rcr"),
[x8616_op_test] = slit8("test"),
[x8616_op_rep] = slit8(""),
[x8616_op_movs] = slit8("movs"),
[x8616_op_cmps] = slit8("cmps"),
[x8616_op_scas] = slit8("scas"),
[x8616_op_lods] = slit8("lods"),
[x8616_op_stos] = slit8("stos"),
[x8616_op_call] = slit8("call"),
[x8616_op_jmp] = slit8("jmp"),
[x8616_op_ret] = slit8("ret"),
[x8616_op_retf] = slit8("retf"),
[x8616_op_je] = slit8("je"),
[x8616_op_jl] = slit8("jl"),
[x8616_op_jle] = slit8("jle"),
[x8616_op_jb] = slit8("jb"),
[x8616_op_jbe] = slit8("jbe"),
[x8616_op_jp] = slit8("jp"),
[x8616_op_jo] = slit8("jo"),
[x8616_op_js] = slit8("js"),
[x8616_op_jne] = slit8("jne"),
[x8616_op_jnl] = slit8("jnl"),
[x8616_op_jg] = slit8("jg"),
[x8616_op_jnb] = slit8("jnb"),
[x8616_op_ja] = slit8("ja"),
[x8616_op_jnp] = slit8("jnp"),
[x8616_op_jno] = slit8("jno"),
[x8616_op_jns] = slit8("jns"),
[x8616_op_loop] = slit8("loop"),
[x8616_op_loopz] = slit8("loopz"),
[x8616_op_loopnz] = slit8("loopnz"),
[x8616_op_jcxz] = slit8("jcxz"),
[x8616_op_int] = slit8("int"),
[x8616_op_int3] = slit8("int3"),
[x8616_op_into] = slit8("into"),
[x8616_op_iret] = slit8("iret"),
[x8616_op_clc] = slit8("clc"),
[x8616_op_cmc] = slit8("cmc"),
[x8616_op_stc] = slit8("stc"),
[x8616_op_cld] = slit8("cld"),
[x8616_op_std] = slit8("std"),
[x8616_op_cli] = slit8("cli"),
[x8616_op_sti] = slit8("sti"),
[x8616_op_hlt] = slit8("hlt"),
[x8616_op_wait] = slit8("wait"),
[x8616_op_lock] = slit8(""),
[x8616_op_segment] = slit8(""),
};
RO_ global Str8 x8616_serialize_reg8[] = {
[x8616_al] = slit8("al"),
[x8616_cl] = slit8("cl"),
[x8616_dl] = slit8("dl"),
[x8616_bl] = slit8("bl"),
[x8616_ah] = slit8("ah"),
[x8616_ch] = slit8("ch"),
[x8616_dh] = slit8("dh"),
[x8616_bh] = slit8("bh"),
};
RO_ global Str8 x8616_serialize_reg16[] = {
[x8616_ax] = slit8("ax"),
[x8616_cx] = slit8("cx"),
[x8616_dx] = slit8("dx"),
[x8616_bx] = slit8("bx"),
[x8616_sp] = slit8("sp"),
[x8616_bp] = slit8("bp"),
[x8616_si] = slit8("si"),
[x8616_di] = slit8("di"),
};
RO_ global Str8 x8616_serialize_seg[] = {
[x8616_es] = slit8("es"),
[x8616_cs] = slit8("cs"),
[x8616_ss] = slit8("ss"),
[x8616_ds] = slit8("ds"),
};
RO_ global Str8 x8616_serialize_ea[] = {
[x8616_ea_bx_si] = slit8("bx + si"),
[x8616_ea_bx_di] = slit8("bx + di"),
[x8616_ea_bp_si] = slit8("bp + si"),
[x8616_ea_bp_di] = slit8("bp + di"),
[x8616_ea_si] = slit8("si"),
[x8616_ea_di] = slit8("di"),
[x8616_ea_bp] = slit8("bp"),
[x8616_ea_bx] = slit8("bx"),
};
typedef Enum_(U1, X8616_SerializeSizeWhere) {
x8616_serialize_size_none = 0x00,
x8616_serialize_size_before_mem = 0x01,
x8616_serialize_size_before_imm = 0x02,
};
FI_ B4 x8616_serialize_put(Str8Gen_R gen, Str8 piece) {
if (piece.len > gen->cap - gen->len) return false;
str8gen_append_str8(gen, piece); return true;
}
FI_ X8616_SerializeStatus x8616_serialize_put_or_full(Str8Gen_R gen, Str8 piece) {
X8616_SerializeStatus status = x8616_serialize_ok;
if (x8616_serialize_put(gen, piece) == 0) status = x8616_serialize_output_full;
return status;
}
internal B4 x8616_serialize_put_u4(Str8Gen_R gen, U4 value) {
Info_str8_from_u4 info = str8_from_u4_info(value, 10, 0, 0);
UTF8 digits[16];
B4 ok = info.size_required != 0 && info.size_required <= Array_len(digits) && info.size_required <= gen->cap - gen->len;
if (ok) {
Str8 text = str8_from_u4_buf(slice_ut(digits, info.size_required), value, 10, 0, 0, info);
ok = x8616_serialize_put(gen, text);
}
return ok;
}
internal B4 x8616_serialize_put_s4(Str8Gen_R gen, S4 value) {
B4 ok = true;
if (value < 0) {
ok = x8616_serialize_put(gen, slit8("-"));
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, -value));
}
else {
ok = x8616_serialize_put_u4(gen, C_(U4, value));
}
return ok;
}
internal S4 x8616_serialize_s4_from_bits(U2 bits, U1 byte_count) {
if (byte_count <= 1) {
U4 value = bits & 0xFF;
if (value & 0x80) return C_(S4, value) - 256;
return C_(S4, value);
}
U4 value = bits;
if (value & 0x8000) return C_(S4, value) - 65536;
return C_(S4, value);
}
FI_ B4 x8616_serialize_imm_is_signed(X8616_Op op) { switch (op) {
case x8616_op_mov:
case x8616_op_add:
case x8616_op_adc:
case x8616_op_sub:
case x8616_op_sbb:
case x8616_op_cmp:
case x8616_op_ret:
case x8616_op_retf:
return 1;
default:
return 0;
}}
FI_ U1 x8616_serialize_imm_bytes(X8616_DecodedOperandFlags flags, U1 immediate_bytes, X8616_WidthMode width) {
if (immediate_bytes) return immediate_bytes;
if (flags & x8616_decoded_operand_sign_extended) return 1;
if (width == x8616_width_word) return 2;
return 1;
}
internal B4
x8616_serialize_put_imm(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand) {
U1 bytes = x8616_serialize_imm_bytes(operand->flags, operand->immediate_bytes, operand->width);
if (x8616_serialize_imm_is_signed(inst->op)) {
return x8616_serialize_put_s4(gen, x8616_serialize_s4_from_bits(operand->immediate, bytes));
}
U4 value = operand->immediate;
if (bytes <= 1) value &= 0xFF;
return x8616_serialize_put_u4(gen, value);
}
internal X8616_WidthMode
x8616_serialize_mem_width(X8616_DecodedInstruction_R inst) {
for (U1 id = 0; id < inst->operand_count; ++id) {
if (inst->operands[id].flags & x8616_decoded_operand_memory) return inst->operands[id].width;
}
return inst->width;
}
internal X8616_SerializeSizeWhere
x8616_serialize_size_where(X8616_Op op, U1 operand_count, X8616_DecodedOperand operands[static 2])
{
B4 has_mem = 0;
B4 has_imm = 0;
for (U1 id = 0; id < operand_count; ++id) {
X8616_DecodedOperandFlags flags = operands[id].flags;
if (flags & x8616_decoded_operand_memory) has_mem = 1;
if ((flags & x8616_decoded_operand_immediate) && ((flags & x8616_decoded_operand_register) == 0)) has_imm = 1;
}
switch (op) {
case x8616_op_mov:
if (has_mem && has_imm) return x8616_serialize_size_before_imm;
return x8616_serialize_size_none;
case x8616_op_add:
case x8616_op_adc:
case x8616_op_sub:
case x8616_op_sbb:
case x8616_op_cmp:
case x8616_op_and:
case x8616_op_or:
case x8616_op_xor:
case x8616_op_test:
if (has_mem && has_imm) return x8616_serialize_size_before_mem;
return x8616_serialize_size_none;
case x8616_op_not:
case x8616_op_neg:
case x8616_op_inc:
case x8616_op_dec:
case x8616_op_mul:
case x8616_op_imul:
case x8616_op_div:
case x8616_op_idiv:
case x8616_op_push:
case x8616_op_pop:
case x8616_op_shl:
case x8616_op_shr:
case x8616_op_sar:
case x8616_op_rol:
case x8616_op_ror:
case x8616_op_rcl:
case x8616_op_rcr:
if (has_mem) return x8616_serialize_size_before_mem;
return x8616_serialize_size_none;
default:
return x8616_serialize_size_none;
}
}
internal B4 x8616_serialize_put_size(Str8Gen_R gen, X8616_WidthMode width) {
Str8 name = slit8("");
if (width == x8616_width_byte) name = slit8("byte");
if (width == x8616_width_word) name = slit8("word");
B4 ok = name.len != 0;
if (ok) ok = x8616_serialize_put(gen, name);
if (ok) ok = x8616_serialize_put(gen, slit8(" "));
return ok;
}
internal B4
x8616_serialize_put_memory(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand)
{
B4 ok = true;
if (inst->prefixes.has_segment) {
ok = x8616_serialize_put(gen, x8616_serialize_seg[inst->prefixes.segment]);
if (ok) ok = x8616_serialize_put(gen, slit8(":"));
}
if (ok) ok = x8616_serialize_put(gen, slit8("["));
if (ok && (operand->flags & x8616_decoded_operand_direct)) {
ok = x8616_serialize_put_u4(gen, operand->address);
}
else if (ok) {
ok = x8616_serialize_put(gen, x8616_serialize_ea[operand->ea]);
S4 disp = operand->displacement;
if (ok && disp > 0) {
ok = x8616_serialize_put(gen, slit8(" + "));
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, disp));
}
else if (ok && disp < 0) {
ok = x8616_serialize_put(gen, slit8(" - "));
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, -disp));
}
}
if (ok) ok = x8616_serialize_put(gen, slit8("]"));
return ok;
}
FI_ B4 x8616_serialize_is_string(X8616_Op op) { switch (op) {
case x8616_op_movs:
case x8616_op_cmps:
case x8616_op_scas:
case x8616_op_lods:
case x8616_op_stos:
return 1;
default:
return 0;
}}
FI_ B4 x8616_serialize_has_memory(X8616_DecodedInstruction* inst) {
for (U1 id = 0; id < inst->operand_count; ++id) { if (inst->operands[id].flags & x8616_decoded_operand_memory) return 1; }
return 0;
}
internal X8616_SerializeStatus
x8616_serialize_put_operand(Str8Gen_R gen, X8616_DecodedInstruction* inst, X8616_DecodedOperand* operand)
{
X8616_SerializeStatus status = x8616_serialize_ok;
X8616_SerializeSizeWhere where = x8616_serialize_size_where(inst->op, inst->operand_count, inst->operands);
X8616_WidthMode width = x8616_serialize_mem_width(inst);
B4 is_mem = (operand->flags & x8616_decoded_operand_memory) != 0;
B4 is_imm = ((operand->flags & x8616_decoded_operand_immediate) != 0) && ((operand->flags & x8616_decoded_operand_register) == 0);
B4 is_reg = (operand->flags & x8616_decoded_operand_register) != 0;
B4 is_seg = (operand->flags & x8616_decoded_operand_segment) != 0;
B4 is_rel = (operand->flags & x8616_decoded_operand_relative) != 0;
B4 is_far = (operand->flags & x8616_decoded_operand_far_ptr) != 0;
if (status == x8616_serialize_ok && where == x8616_serialize_size_before_mem && is_mem) {
if (x8616_serialize_put_size(gen, width) == 0) status = x8616_serialize_output_full;
}
if (status == x8616_serialize_ok && where == x8616_serialize_size_before_imm && is_imm) {
if (x8616_serialize_put_size(gen, width) == 0) status = x8616_serialize_output_full;
}
if (status == x8616_serialize_ok && (inst->flags & x8616_encoding_far) && is_mem) {
status = x8616_serialize_put_or_full(gen, slit8("far "));
}
if (status == x8616_serialize_ok) {
if (is_reg) {
U1 index = C_(U1, operand->reg.r16);
if (operand->width == x8616_width_byte) status = x8616_serialize_put_or_full(gen, x8616_serialize_reg8 [index]);
else if (operand->width == x8616_width_word) status = x8616_serialize_put_or_full(gen, x8616_serialize_reg16[index]);
else status = x8616_serialize_unsupported_form;
}
else if (is_seg) {
status = x8616_serialize_put_or_full(gen, x8616_serialize_seg[operand->segment]);
}
else if (is_mem) {
if (x8616_serialize_put_memory(gen, inst, operand) == 0) status = x8616_serialize_output_full;
}
else if (is_imm) {
if (x8616_serialize_put_imm(gen, inst, operand) == 0) status = x8616_serialize_output_full;
}
else if (is_rel) {
S4 rel = C_(S4, inst->size) + operand->displacement;
status = x8616_serialize_put_or_full(gen, slit8("$"));
if (status == x8616_serialize_ok && rel >= 0) status = x8616_serialize_put_or_full(gen, slit8("+"));
if (status == x8616_serialize_ok && x8616_serialize_put_s4(gen, rel) == 0) status = x8616_serialize_output_full;
}
else if (is_far) {
if (x8616_serialize_put_u4(gen, operand->far_segment) == 0) status = x8616_serialize_output_full;
if (status == x8616_serialize_ok) status = x8616_serialize_put_or_full(gen, slit8(":"));
if (status == x8616_serialize_ok && x8616_serialize_put_u4(gen, operand->far_offset) == 0) status = x8616_serialize_output_full;
}
else {
status = x8616_serialize_unsupported_form;
}
}
return status;
}
FI_ X8616_DecodedOperandFlags x8616_serialize_base_flags(X8616_DecodedOperandFlags flags) {
return flags & (
x8616_decoded_operand_register
| x8616_decoded_operand_segment
| x8616_decoded_operand_memory
| x8616_decoded_operand_immediate
| x8616_decoded_operand_relative
| x8616_decoded_operand_far_ptr
);
}
FI_ B4 x8616_serialize_one_flag(X8616_DecodedOperandFlags flags) { U2 bits = C_(U2, flags); return (bits != 0) && ((bits & (bits - 1)) == 0); }
internal X8616_SerializeStatus
x8616_serialize_validate(X8616_DecodedInstruction_R inst)
{
X8616_SerializeStatus status = x8616_serialize_ok;
B4 bad_decode = inst->decode_flags & (x8616_decode_invalid | x8616_decode_truncated);
B4 invalid_sig = inst->size == 0 || inst->operand_count > 2;
B4 invalid_mnemonic = u4_(inst->op) >= Array_len(x8616_serialize_mnemonic) || inst->op == x8616_op_invalid;
B4 invalid_prefix_with_seg = inst->prefixes.has_segment && u1_(inst->prefixes.segment) >= Array_len(x8616_serialize_seg);
if (bad_decode || invalid_sig || invalid_mnemonic || invalid_prefix_with_seg) {
status = x8616_serialize_invalid_record; goto status_failed;
}
B4 bad_prefix_segement = inst->prefixes.has_segment && (x8616_serialize_has_memory(inst) == 0);
B4 bad_prefix_repeat = inst->prefixes.has_repeat && (x8616_serialize_is_string(inst->op) == 0);
if (bad_prefix_segement || bad_prefix_repeat) {
status = x8616_serialize_unsupported_form; goto status_failed;
}
for (U1 id = 0; id < inst->operand_count; ++id)
{
X8616_DecodedOperand_R operand = & inst->operands[id];
X8616_DecodedOperandFlags base = x8616_serialize_base_flags(operand->flags);
B4 invalid_flag = x8616_serialize_one_flag(base) == 0;
B4 has_operand_register = base & x8616_decoded_operand_register;
B4 has_operand_segment = base & x8616_decoded_operand_segment;
B4 has_operand_memory = base & x8616_decoded_operand_memory;
B4 invalid_reg_r16 = u1_(operand->reg.r16) >= Array_len(x8616_serialize_reg16);
B4 invalid_width = operand->width != x8616_width_byte && operand->width != x8616_width_word;
B4 invalid_operand_seg = u1_(operand->segment) >= Array_len(x8616_serialize_seg);
B4 invalid_operand_ea = u1_(operand->ea) >= Array_len(x8616_serialize_ea);
B4 invalid_direct_ea = has_operand_memory && ((operand->flags & x8616_decoded_operand_direct) == 0) && invalid_operand_ea;
B4 invalid_operand = invalid_flag
|| (has_operand_register && (invalid_reg_r16 || invalid_width))
|| (has_operand_segment && invalid_operand_seg)
|| invalid_direct_ea;
if (invalid_operand) {
status = x8616_serialize_invalid_record; goto status_failed;
}
}
status_failed:
return status;
}
internal X8616_SerializeStatus
x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst)
{
X8616_SerializeStatus st = x8616_serialize_ok;
Str8 mnemonic = x8616_serialize_mnemonic[inst->op];
if (mnemonic.len == 0) st = x8616_serialize_unsupported_form;
if (st == x8616_serialize_ok && inst->prefixes.lock) {
st = x8616_serialize_put_or_full(line, slit8("lock "));
}
if (st == x8616_serialize_ok && inst->prefixes.has_repeat) {
if (inst->prefixes.repeat == x8616_rep) st = x8616_serialize_put_or_full(line, slit8("rep "));
else st = x8616_serialize_put_or_full(line, slit8("repne "));
}
if (st == x8616_serialize_ok) st = x8616_serialize_put_or_full(line, mnemonic);
if (st == x8616_serialize_ok && x8616_serialize_is_string(inst->op)) {
if (inst->width == x8616_width_byte) st = x8616_serialize_put_or_full(line, slit8("b"));
else if (inst->width == x8616_width_word) st = x8616_serialize_put_or_full(line, slit8("w"));
else st = x8616_serialize_unsupported_form;
}
if (st == x8616_serialize_ok && inst->operand_count) {
st = x8616_serialize_put_or_full(line, slit8(" "));
for (U1 id = 0; st == x8616_serialize_ok && id < inst->operand_count; ++id) {
if (id) st = x8616_serialize_put_or_full(line, slit8(", "));
if (st == x8616_serialize_ok) st = x8616_serialize_put_operand(line, inst, & inst->operands[id]);
}
}
if (st == x8616_serialize_ok) st = x8616_serialize_put_or_full(line, slit8("\n"));
return st;
}
X8616_SerializeInfo
x8616_serialize_instructions(X8616_SerializeRequest request)
{
X8616_SerializeInfo result = {0}; result.text.ptr = C_(UTF8*, request.output.ptr);
B4 invalid_record =
(request.instruction_count && request.instructions == 0)
|| (request.output.len && request.output.ptr == 0)
|| (request.scratch.len && request.scratch.ptr == 0);
if (invalid_record) { result.status = x8616_serialize_invalid_record; goto exit; }
if (request.output.len < X8616_SERIALIZE_HEADER_LEN) { result.status = x8616_serialize_output_full; goto exit; }
Str8Gen gen = str8gen_make(request.output);
if (x8616_serialize_header.len > gen.cap - gen.len) { result.status = x8616_serialize_output_full; goto exit; }
str8gen_append_str8(& gen, x8616_serialize_header);
result.text.len = gen.len;
for (U4 id = 0; id < request.instruction_count; ++id) {
X8616_SerializeStatus line_status = x8616_serialize_validate(& request.instructions[id]);
if (line_status != x8616_serialize_ok) { result.status = line_status; goto exit; }
Str8Gen line = str8gen_make(request.scratch);
line_status = x8616_serialize_instruction_line(& line, & request.instructions[id]);
if (line_status != x8616_serialize_ok) { result.status = line_status; goto exit; }
Str8 text = str8(line.ptr, line.len);
if (text.len > gen.cap - gen.len) { result.status = x8616_serialize_output_full; goto exit; }
str8gen_append_str8(& gen, text);
result.text.len = gen.len;
result.instructions_written += 1;
}
result.status = x8616_serialize_ok;
exit:
return result;
}
+26
View File
@@ -0,0 +1,26 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "decoder.h"
#endif
typedef Enum_(U1, X8616_SerializeStatus) {
x8616_serialize_ok = 0x00,
x8616_serialize_output_full = 0x01,
x8616_serialize_invalid_record = 0x02,
x8616_serialize_unsupported_form = 0x03,
};
typedef Struct_(X8616_SerializeRequest) {
X8616_DecodedInstruction* instructions;
U4 instruction_count;
Slice output;
Slice scratch;
};
typedef Struct_(X8616_SerializeInfo) {
Str8 text;
U4 instructions_written;
X8616_SerializeStatus status;
};
X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request);
+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;
+8 -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
@@ -221,6 +222,10 @@ def_signed_ops(le, <=)
#define dbg_args(...) __VA_ARGS__ #define dbg_args(...) __VA_ARGS__
#pragma region Control Flow & Iteration #pragma region Control Flow & Iteration
#define jump_ne(a,b,label) if (a != b) goto label
#define jump_gt(a,b,label) if (a > b) goto label
#define jump_lt(a,b,label) if (a < b) goto label
#define unreachable() __builtin_unreachable() #define unreachable() __builtin_unreachable()
#define each_iter(type, iter, end) (type iter = 0; iter < end; ++ iter) #define each_iter(type, iter, end) (type iter = 0; iter < end; ++ iter)
@@ -277,8 +282,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),
+46 -6
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,17 @@
#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/serializer.h"
#include "8086/gen/decoder_table.h"
#include "8086/decoder.c"
#include "8086/serializer.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; };
@@ -47,7 +59,6 @@ FI_ void a8utf8_from_u1_be(UTF8 out[8], U1 value) {
I_ U4 binary_as_str8_eval_len(Slice_U1 data) { return data.len * 8; } I_ U4 binary_as_str8_eval_len(Slice_U1 data) { return data.len * 8; }
#define jump_lt(a,b,label) if (a < b) goto label
I_ Str8 binary_as_str8(Slice_U1 data, FArena* str8_mem) { Str8 result = {0}; I_ Str8 binary_as_str8(Slice_U1 data, FArena* str8_mem) { Str8 result = {0};
U4 req_len = data.len * 8; jump_lt(str8_mem->capacity,req_len, jret); U4 req_len = data.len * 8; jump_lt(str8_mem->capacity,req_len, jret);
@@ -56,22 +67,24 @@ 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)];
UTF8 text_mem [kilo(16)];
}; };
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 +93,35 @@ 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,
);
if (info.source_consumed != data.len || info.instruction_count == 0 || info.msgs.error_count || info.msgs.dropped_count) {
ms_exit_process(10);
return 10;
}
X8616_SerializeInfo text = x8616_serialize_instructions((X8616_SerializeRequest){
.instructions = decoded.ptr,
.instruction_count = info.instruction_count,
.output = slice_ut_arr(smem.text_mem),
.scratch = slice_ut_arr(smem.Scratchpad),
});
if (text.status != x8616_serialize_ok || text.instructions_written != info.instruction_count) {
ms_exit_process(13);
return 13;
}
Str8 listing_text = text.text;
(void)listing_text;
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