This commit is contained in:
ed
2026-09-09 12:38:18 -04:00
parent d3fd791537
commit 588fa20778
9 changed files with 164 additions and 148 deletions
+44 -43
View File
@@ -39,18 +39,18 @@ typedef Struct_(X8616_DecodePlex) {
U1 post_opcode; U1 post_opcode;
U1 mod_rm; U1 mod_rm;
U1 d; X8616_Direction d;
U1 w; X8616_Width w;
U1 s; X8616_Sign s;
U1 v; X8616_VariableShift v;
U1 z; X8616_Repeat z;
U1 reg_opcode; X8616_DecodedReg reg_opcode;
U1 sr_opcode; X8616_Segment sr_opcode;
U1 mod; X8616_Mod mod;
U1 reg; X8616_DecodedReg reg;
U1 rm; X8616_EA rm;
U1 sr_modrm; X8616_Segment sr_modrm;
X8616_WidthMode width; X8616_WidthMode width;
@@ -103,11 +103,11 @@ x8616_decode_apply_prefix(X8616_DecodePlex_R plex, X8616_DecodePlan_R plan, U1 o
plex->prefixes.lock |= plan->prefix_kind == x8616_prefix_lock; plex->prefixes.lock |= plan->prefix_kind == x8616_prefix_lock;
if (plan->prefix_kind == x8616_prefix_repeat) { if (plan->prefix_kind == x8616_prefix_repeat) {
plex->prefixes.has_repeat = 1; plex->prefixes.has_repeat = 1;
plex->prefixes.repeat = (opcode >> plan->z_shift) & 0b1; plex->prefixes.repeat = C_(X8616_Repeat, (opcode >> plan->z_shift) & 0b1);
} }
if (plan->prefix_kind == x8616_prefix_segment) { if (plan->prefix_kind == x8616_prefix_segment) {
plex->prefixes.has_segment = 1; plex->prefixes.has_segment = 1;
plex->prefixes.segment = (opcode >> plan->sr_shift) & 0b11; plex->prefixes.segment = C_(X8616_Segment, (opcode >> plan->sr_shift) & 0b11);
} }
} }
@@ -251,13 +251,13 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
} }
X8616_DecodePlan const* plan = plex->plan; X8616_DecodePlan const* plan = plex->plan;
plex->d = (plex->opcode >> plan->d_shift) & 0b1; plex->d = C_(X8616_Direction, (plex->opcode >> plan->d_shift) & 0b1);
plex->w = (plex->opcode >> plan->w_shift) & 0b1; plex->w = C_(X8616_Width, (plex->opcode >> plan->w_shift) & 0b1);
plex->s = (plex->opcode >> plan->s_shift) & 0b1; plex->s = C_(X8616_Sign, (plex->opcode >> plan->s_shift) & 0b1);
plex->v = (plex->opcode >> plan->v_shift) & 0b1; plex->v = C_(X8616_VariableShift, (plex->opcode >> plan->v_shift) & 0b1);
plex->z = (plex->opcode >> plan->z_shift) & 0b1; plex->z = C_(X8616_Repeat, (plex->opcode >> plan->z_shift) & 0b1);
plex->reg_opcode = (plex->opcode >> plan->reg_shift) & 0b111; plex->reg_opcode.r16 = C_(X8616_Reg16, (plex->opcode >> plan->reg_shift) & 0b111);
plex->sr_opcode = (plex->opcode >> plan->sr_shift) & 0b11; plex->sr_opcode = C_(X8616_Segment, (plex->opcode >> plan->sr_shift) & 0b11);
plex->width = plan->width; plex->width = plan->width;
if (plex->width == x8616_width_dynamic && (plan->flags & x8616_plan_has_w)) if (plex->width == x8616_width_dynamic && (plan->flags & x8616_plan_has_w))
@@ -272,16 +272,16 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
if (plan->flags & x8616_plan_has_modrm) { if (plan->flags & x8616_plan_has_modrm) {
plex->mod_rm = plex->body[plex->body_at]; plex->mod_rm = plex->body[plex->body_at];
plex->mod = x8616_modrm_mod(plex->mod_rm); plex->mod = C_(X8616_Mod, x8616_modrm_mod(plex->mod_rm));
plex->reg = x8616_modrm_reg(plex->mod_rm); plex->reg.r16 = C_(X8616_Reg16, x8616_modrm_reg(plex->mod_rm));
plex->rm = x8616_modrm_rm(plex->mod_rm); plex->rm = C_(X8616_EA, x8616_modrm_rm(plex->mod_rm));
plex->sr_modrm = x8616_modrm_sr(plex->mod_rm); plex->sr_modrm = C_(X8616_Segment, x8616_modrm_sr(plex->mod_rm));
plex->body_at += 1; plex->body_at += 1;
} }
plex->displacement_at = plex->body_at; plex->displacement_at = plex->body_at;
if (plan->flags & x8616_plan_uses_rm) plex->displacement_bytes = x8616_decode_disp_bytes[(plex->mod << 3) | plex->rm]; if (plan->flags & x8616_plan_uses_rm) plex->displacement_bytes = x8616_decode_disp_bytes[(u1_(plex->mod) << 3) | u1_(plex->rm)];
plex->direct_memory = (plan->flags & x8616_plan_uses_rm) && plex->mod == x8616_mod_mem && plex->rm == x8616_ea_direct; plex->direct_memory = (plan->flags & x8616_plan_uses_rm) && plex->mod == x8616_mod_mem && plex->rm == x8616_ea_direct;
@@ -321,19 +321,19 @@ 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.r16 = C_(X8616_Reg16, plex->reg); source[x8616_operand_reg_modrm].reg = 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.r16 = C_(X8616_Reg16, plex->reg_opcode); source[x8616_operand_reg_opcode].reg = 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 = C_(X8616_Segment, plex->sr_modrm); source[x8616_operand_segment_modrm].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 = C_(X8616_Segment, plex->sr_opcode); source[x8616_operand_segment_opcode].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;
@@ -350,8 +350,8 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
} }
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 = C_(X8616_Mod, plex->mod); source[x8616_operand_rm].mod = plex->mod;
source[x8616_operand_rm].ea = C_(X8616_EA, plex->rm); source[x8616_operand_rm].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) {
@@ -407,7 +407,7 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
} }
// Final projection. Authored operand order is d=0; d=1 exchanges the two source slots without introducing a separate decoder path. // Final projection. Authored operand order is d=0; d=1 exchanges the two source slots without introducing a separate decoder path.
U1 swap = C_(U1, ((plan->flags & x8616_plan_has_d) != 0) & plex->d); U1 swap = C_(U1, ((plan->flags & x8616_plan_has_d) != 0) & u1_(plex->d));
plex->instruction.operands[swap] = source[plan->operands[0]]; plex->instruction.operands[swap] = source[plan->operands[0]];
plex->instruction.operands[swap ^ 1] = source[plan->operands[1]]; plex->instruction.operands[swap ^ 1] = source[plan->operands[1]];
@@ -416,11 +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 = x8616_decode_opcode(plan, plex->opcode); plex->instruction.opcode = x8616_decode_opcode(plan, plex->opcode);
plex->instruction.d = C_(X8616_Direction, (plan->flags & x8616_plan_has_d) ? plex->d : 0); plex->instruction.d = (plan->flags & x8616_plan_has_d) ? plex->d : x8616_d_rm_dst;
plex->instruction.w = C_(X8616_Width, (plan->flags & x8616_plan_has_w) ? plex->w : 0); plex->instruction.w = (plan->flags & x8616_plan_has_w) ? plex->w : x8616_w_byte;
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;
U4 total_available = plex->source_size; U4 total_available = plex->source_size;
@@ -435,27 +435,28 @@ x8616_decode_one_plex(X8616_DecodePlex* plex)
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request) X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request)
{ {
X8616_DecodeInfo result = {0}; X8616_DecodeInfo result = {0};
result.instruction_capacity = request.instruction_capacity; result.instruction_cap = request.instruction_cap;
while (result.source_consumed < request.source_size && result.instruction_count < request.instruction_capacity) { while (result.source_consumed < request.source_len && result.instruction_count < request.instruction_cap) {
X8616_DecodePlex plex = {0}; X8616_DecodePlex plex = {0};
plex.source = request.source + result.source_consumed; plex.source = request.source + result.source_consumed;
plex.source_size = request.source_size - result.source_consumed; plex.source_size = request.source_len - result.source_consumed;
plex.source_offset = result.source_consumed; plex.source_offset = result.source_consumed;
plex.info_arena = request.info_arena; plex.info_arena = request.info_arena;
plex.msgs = & result.msgs; plex.msgs = & result.msgs;
U4 consumed = x8616_decode_one_plex(& plex); U4 consumed = x8616_decode_one_plex(& plex);
request.instructions[result.instruction_count++] = plex.instruction; request.out_instructions[result.instruction_count] = plex.instruction;
result.instruction_count += 1;
if (consumed == false) consumed = 1; if (consumed == false) consumed = 1;
result.source_consumed += consumed; result.source_consumed += consumed;
} }
if (result.source_consumed < request.source_size && result.instruction_count == request.instruction_capacity) { if (result.source_consumed < request.source_len && result.instruction_count == request.instruction_cap) {
x8616_info_push(request.info_arena, & result.msgs, x8616_info_warning x8616_info_push(request.info_arena, & result.msgs, x8616_info_warning
, x8616_info_output_full , x8616_info_output_full
, result.source_consumed , result.source_consumed
, 0 , 0
, request.instruction_capacity , request.instruction_cap
, result.instruction_count , result.instruction_count
); );
} }
+10 -13
View File
@@ -67,11 +67,10 @@ typedef Struct_(X8616_DecodedInstruction) {
X8616_DecodeFlags decode_flags; X8616_DecodeFlags decode_flags;
X8616_WidthMode width; X8616_WidthMode width;
X8616_DecodedPrefixes prefixes; X8616_DecodedPrefixes prefixes;
X8616_DecodedOperand operands[2]; X8616_DecodedOperand operands[2]; U1 operand_count;
U1 operand_count; X8616_OpcodePrefix opcode;
X8616_OpcodePrefix opcode; X8616_Direction d;
X8616_Direction d; X8616_Width w;
X8616_Width w;
B1 has_mod_rm; B1 has_mod_rm;
U1 size; U1 size;
U1 size_required; U1 size_required;
@@ -142,20 +141,18 @@ enum {
}; };
typedef Struct_(X8616_DecodeRequest) { typedef Struct_(X8616_DecodeRequest) {
U1* source; U1* source;
U4 source_size; X8616_DecodedInstruction* out_instructions;
U4 source_len;
X8616_DecodedInstruction* instructions; U4 instruction_cap;
U4 instruction_capacity;
FArena* info_arena; FArena* info_arena;
}; };
typedef Struct_(X8616_DecodeInfo) { typedef Struct_(X8616_DecodeInfo) {
X8616_InfoList msgs;
U4 source_consumed; U4 source_consumed;
U4 instruction_count; U4 instruction_count;
U4 instruction_capacity; U4 instruction_cap;
X8616_InfoList msgs;
}; };
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request); X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request);
+6 -6
View File
@@ -3,15 +3,15 @@
# include "encoder.h" # include "encoder.h"
#endif #endif
// ============================================================================ // =========================================================================================
// Encoding Table // Encoding Table
// //
// Part 1 target: the instruction cross-section exercised by Computer Enhance // Part 1 target: the instruction cross-section exercised by Computer Enhance listing 0042.
// listing 0042. Later Part 1 simulation listings use a subset of this table. // Later Part 1 simulation listings use a subset of this table.
// //
// Fixed opcode bits are kept in binary/signature form; ModR/M /digit selectors // Fixed opcode bits are kept in binary/signature form;
// use their encoded enumeration values. // ModR/M /digit selectors use their encoded enumeration values.
// ============================================================================ // =========================================================================================
RO_ global X8616_Encoding x8616_encodings[] = RO_ global X8616_Encoding x8616_encodings[] =
{ {
+21 -12
View File
@@ -26,6 +26,11 @@ typedef Enum_(U1, X8616_InfoCode) {
x8616_info_gen_ambiguous_decode = 0x09, x8616_info_gen_ambiguous_decode = 0x09,
x8616_info_gen_dispatch_mismatch = 0x0A, x8616_info_gen_dispatch_mismatch = 0x0A,
x8616_info_serialize_bad_request = 0x0B,
x8616_info_serialize_invalid_record = 0x0C,
x8616_info_serialize_unsupported_form = 0x0D,
x8616_info_serialize_output_full = 0x0E,
x8616_info_count, x8616_info_count,
}; };
@@ -35,8 +40,8 @@ typedef Struct_(X8616_InfoMsg) {
X8616_InfoMsg* next; X8616_InfoMsg* next;
X8616_InfoKind kind; X8616_InfoKind kind;
X8616_InfoCode code; X8616_InfoCode code;
U4 source_offset;
U2 source_size; U2 source_size;
U4 source_offset;
U4 expected; U4 expected;
U4 actual; U4 actual;
Str8 text; Str8 text;
@@ -45,17 +50,21 @@ typedef Struct_(X8616_InfoMsg) {
/* Static templates use the same <identifier> vocabulary as Duffle's str8_fmt_ktl_buf path. /* Static templates use the same <identifier> vocabulary as Duffle's str8_fmt_ktl_buf path.
The decoder itself never expands these. */ The decoder itself never expands these. */
RO_ global Str8 x8616_info_templates[x8616_info_count] = { RO_ global Str8 x8616_info_templates[x8616_info_count] = {
[x8616_info_none] = slit8(""), [x8616_info_none] = slit8(""),
[x8616_info_invalid_opcode] = slit8("Opcode <actual> is not in the Part 1 8086 decode table at <offset>."), [x8616_info_invalid_opcode] = slit8("Opcode <actual> is not in the Part 1 8086 decode table at <offset>."),
[x8616_info_invalid_opcode_extension] = slit8("Opcode extension <actual> does not match the selected encoding at <offset>."), [x8616_info_invalid_opcode_extension] = slit8("Opcode extension <actual> does not match the selected encoding at <offset>."),
[x8616_info_invalid_post_opcode] = slit8("Post-opcode byte <actual> does not match expected <expected> at <offset>."), [x8616_info_invalid_post_opcode] = slit8("Post-opcode byte <actual> does not match expected <expected> at <offset>."),
[x8616_info_truncated_instruction] = slit8("Instruction at <offset> needs <expected> bytes; <actual> are available."), [x8616_info_truncated_instruction] = slit8("Instruction at <offset> needs <expected> bytes; <actual> are available."),
[x8616_info_output_full] = slit8("Decoded-instruction output is full: capacity <expected>, produced <actual>."), [x8616_info_output_full] = slit8("Decoded-instruction output is full: capacity <expected>, produced <actual>."),
[x8616_info_gen_multiple_payloads] = slit8("Encoding <offset> describes more than one stream payload."), [x8616_info_gen_multiple_payloads] = slit8("Encoding <offset> describes more than one stream payload."),
[x8616_info_gen_body_cap_exceeded] = slit8("Encoding <offset> requires <actual> body bytes; decoder body capacity is <expected>."), [x8616_info_gen_body_cap_exceeded] = slit8("Encoding <offset> requires <actual> body bytes; decoder body capacity is <expected>."),
[x8616_info_gen_aux_cap_exceeded] = slit8("Generated auxiliary decode table exceeds capacity <expected>."), [x8616_info_gen_aux_cap_exceeded] = slit8("Generated auxiliary decode table exceeds capacity <expected>."),
[x8616_info_gen_ambiguous_decode] = slit8("Decode is ambiguous for opcode/second-byte key <offset>: plans <expected> and <actual>."), [x8616_info_gen_ambiguous_decode] = slit8("Decode is ambiguous for opcode/second-byte key <offset>: plans <expected> and <actual>."),
[x8616_info_gen_dispatch_mismatch] = slit8("Generated dispatch mismatch for opcode/second-byte key <offset>: expected <expected>, actual <actual>."), [x8616_info_gen_dispatch_mismatch] = slit8("Generated dispatch mismatch for opcode/second-byte key <offset>: expected <expected>, actual <actual>."),
[x8616_info_serialize_bad_request] = slit8("Serialize request is missing instructions, output, scratch, or info arena."),
[x8616_info_serialize_invalid_record] = slit8("Serialize record <offset> is not printable (op <actual>)."),
[x8616_info_serialize_unsupported_form] = slit8("Serialize record <offset> has an unsupported display form (op <actual>)."),
[x8616_info_serialize_output_full] = slit8("Serialize output is full at record <offset>: capacity <expected>, produced <actual>."),
}; };
typedef Struct_(X8616_InfoList) { typedef Struct_(X8616_InfoList) {
-4
View File
@@ -5,10 +5,6 @@
# include "info.h" # include "info.h"
#endif #endif
/* Numeric representation remains a presentation decision.
Feed whatever Duffle-formatted Str8 values you want here (hex for opcode
facts, decimal for capacities, etc.) and the existing <key> formatter does
the composition. */
typedef Struct_(X8616_InfoTextValues) { Str8 offset; Str8 expected; Str8 actual; }; typedef Struct_(X8616_InfoTextValues) { Str8 offset; Str8 expected; Str8 actual; };
FI_ Str8 FI_ Str8
+68 -26
View File
@@ -2,10 +2,6 @@
# include "serializer.h" # include "serializer.h"
#endif #endif
enum {
X8616_SERIALIZE_HEADER_LEN = 9,
};
RO_ global Str8 x8616_serialize_header = slit8("bits 16\n\n"); RO_ global Str8 x8616_serialize_header = slit8("bits 16\n\n");
RO_ global Str8 x8616_serialize_mnemonic[] = { RO_ global Str8 x8616_serialize_mnemonic[] = {
@@ -162,12 +158,11 @@ FI_ X8616_SerializeStatus x8616_serialize_put_or_full(Str8Gen_R gen, Str8 piece)
} }
internal B4 x8616_serialize_put_u4(Str8Gen_R gen, U4 value) { internal B4 x8616_serialize_put_u4(Str8Gen_R gen, U4 value) {
Info_str8_from_u4 info = str8_from_u4_info(value, 10, 0, 0); Info_str8_from_u4 info = str8_from_u4_info(value, 10, 0, 0); UTF8 digits[16];
UTF8 digits[16]; B4 ok = info.size_required != 0 && info.size_required <= Array_len(digits) && info.size_required <= gen->cap - gen->len;
B4 ok = info.size_required != 0 && info.size_required <= Array_len(digits) && info.size_required <= gen->cap - gen->len;
if (ok) { if (ok) {
Str8 text = str8_from_u4_buf(slice_ut(digits, info.size_required), value, 10, 0, 0, info); Str8 text = str8_from_u4_buf(slice_ut(digits, info.size_required), value, 10, 0, 0, info);
ok = x8616_serialize_put(gen, text); ok = x8616_serialize_put(gen, text);
} }
return ok; return ok;
} }
@@ -333,13 +328,13 @@ FI_ B4 x8616_serialize_is_string(X8616_Op op) { switch (op) {
return 0; return 0;
}} }}
FI_ B4 x8616_serialize_has_memory(X8616_DecodedInstruction* inst) { FI_ B4 x8616_serialize_has_memory(X8616_DecodedInstruction_R inst) {
for (U1 id = 0; id < inst->operand_count; ++id) { if (inst->operands[id].flags & x8616_decoded_operand_memory) return 1; } for (U1 id = 0; id < inst->operand_count; ++id) { if (inst->operands[id].flags & x8616_decoded_operand_memory) return 1; }
return 0; return 0;
} }
internal X8616_SerializeStatus internal X8616_SerializeStatus
x8616_serialize_put_operand(Str8Gen_R gen, X8616_DecodedInstruction* inst, X8616_DecodedOperand* operand) x8616_serialize_put_operand(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand)
{ {
X8616_SerializeStatus status = x8616_serialize_ok; X8616_SerializeStatus status = x8616_serialize_ok;
X8616_SerializeSizeWhere where = x8616_serialize_size_where(inst->op, inst->operand_count, inst->operands); X8616_SerializeSizeWhere where = x8616_serialize_size_where(inst->op, inst->operand_count, inst->operands);
@@ -408,6 +403,21 @@ FI_ X8616_DecodedOperandFlags x8616_serialize_base_flags(X8616_DecodedOperandFla
FI_ B4 x8616_serialize_one_flag(X8616_DecodedOperandFlags flags) { U2 bits = C_(U2, flags); return (bits != 0) && ((bits & (bits - 1)) == 0); } FI_ B4 x8616_serialize_one_flag(X8616_DecodedOperandFlags flags) { U2 bits = C_(U2, flags); return (bits != 0) && ((bits & (bits - 1)) == 0); }
internal void
x8616_serialize_push(FArena_R arena, X8616_InfoList_R msgs, X8616_SerializeStatus status, U4 id, U2 size, U4 expected, U4 actual) {
if (status == x8616_serialize_ok || arena == 0) return;
X8616_InfoKind kind = x8616_info_error;
X8616_InfoCode code = x8616_info_serialize_invalid_record;
if (status == x8616_serialize_output_full) {
kind = x8616_info_warning;
code = x8616_info_serialize_output_full;
}
else if (status == x8616_serialize_unsupported_form) {
code = x8616_info_serialize_unsupported_form;
}
x8616_info_push(arena, msgs, kind, code, id, size, expected, actual);
}
internal X8616_SerializeStatus internal X8616_SerializeStatus
x8616_serialize_validate(X8616_DecodedInstruction_R inst) x8616_serialize_validate(X8616_DecodedInstruction_R inst)
{ {
@@ -452,7 +462,7 @@ status_failed:
return status; return status;
} }
internal X8616_SerializeStatus internal X8616_SerializeStatus
x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst) x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst)
{ {
X8616_SerializeStatus st = x8616_serialize_ok; X8616_SerializeStatus st = x8616_serialize_ok;
@@ -477,7 +487,7 @@ x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst)
if (st == x8616_serialize_ok && inst->operand_count) { if (st == x8616_serialize_ok && inst->operand_count) {
st = x8616_serialize_put_or_full(line, slit8(" ")); st = x8616_serialize_put_or_full(line, slit8(" "));
for (U1 id = 0; st == x8616_serialize_ok && id < inst->operand_count; ++id) { for (U1 id = 0; st == x8616_serialize_ok && id < inst->operand_count; ++id) {
if (id) st = x8616_serialize_put_or_full(line, slit8(", ")); 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_operand(line, inst, & inst->operands[id]);
} }
} }
@@ -485,38 +495,70 @@ x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst)
return st; return st;
} }
X8616_SerializeInfo X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request)
x8616_serialize_instructions(X8616_SerializeRequest request)
{ {
X8616_SerializeInfo result = {0}; result.text.ptr = C_(UTF8*, request.output.ptr); X8616_SerializeInfo result = {0}; result.text.ptr = C_(UTF8*, request.output.ptr);
B4 invalid_record = X8616_InfoList local = {0};
X8616_InfoList_R msgs = request.msgs ? request.msgs : & local;
B4 bad_request =
(request.instruction_count && request.instructions == 0) (request.instruction_count && request.instructions == 0)
|| (request.output.len && request.output.ptr == 0) || (request.output.len && request.output.ptr == 0)
|| (request.scratch.len && request.scratch.ptr == 0); || (request.scratch.len && request.scratch.ptr == 0)
if (invalid_record) { result.status = x8616_serialize_invalid_record; goto exit; } || (request.info_arena == 0);
if (request.output.len < X8616_SERIALIZE_HEADER_LEN) { result.status = x8616_serialize_output_full; goto exit; } if (bad_request)
{
if (request.info_arena) {
x8616_info_push(request.info_arena, msgs, x8616_info_error
, x8616_info_serialize_bad_request, 0, 0, 0, 0);
}
else {
msgs->count += 1;
msgs->error_count += 1;
msgs->dropped_count += 1;
}
goto exit;
}
if (request.output.len < x8616_serialize_header.len) {
x8616_serialize_push(request.info_arena, msgs, x8616_serialize_output_full
, 0, 0, u4_(x8616_serialize_header.len), u4_(request.output.len));
goto exit;
}
Str8Gen gen = str8gen_make(request.output); 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); str8gen_append_str8(& gen, x8616_serialize_header);
result.text.len = gen.len; result.text.len = gen.len;
for (U4 id = 0; id < request.instruction_count; ++id) { 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; } X8616_DecodedInstruction_R inst = & request.instructions[id];
X8616_SerializeStatus line_status = x8616_serialize_validate(inst);
if (line_status != x8616_serialize_ok) {
x8616_serialize_push(request.info_arena, msgs, line_status
, id, inst->size, 0, u4_(inst->op));
continue;
}
Str8Gen line = str8gen_make(request.scratch); Str8Gen line = str8gen_make(request.scratch);
line_status = x8616_serialize_instruction_line(& line, & request.instructions[id]); line_status = x8616_serialize_instruction_line(& line, inst);
if (line_status != x8616_serialize_ok) { result.status = line_status; goto exit; } if (line_status != x8616_serialize_ok) {
x8616_serialize_push(request.info_arena, msgs, line_status
, id, inst->size, u4_(request.scratch.len), u4_(line.len));
continue;
}
Str8 text = str8(line.ptr, line.len); Str8 text = str8(line.ptr, line.len);
if (text.len > gen.cap - gen.len) { result.status = x8616_serialize_output_full; goto exit; } if (text.len > gen.cap - gen.len) {
x8616_serialize_push(request.info_arena, msgs, x8616_serialize_output_full
, id, inst->size, u4_(request.output.len), u4_(gen.len));
goto exit;
}
str8gen_append_str8(& gen, text); str8gen_append_str8(& gen, text);
result.text.len = gen.len; result.text.len = gen.len;
result.instructions_written += 1; result.instructions_written += 1;
} }
result.status = x8616_serialize_ok;
exit: exit:
result.msgs = *msgs;
return result; return result;
} }
+7 -4
View File
@@ -12,15 +12,18 @@ typedef Enum_(U1, X8616_SerializeStatus) {
typedef Struct_(X8616_SerializeRequest) { typedef Struct_(X8616_SerializeRequest) {
X8616_DecodedInstruction* instructions; X8616_DecodedInstruction* instructions;
U4 instruction_count; U4 instruction_count; byte_pad(4);
Slice output; Slice output;
Slice scratch; Slice scratch;
FArena* info_arena;
X8616_InfoList_R msgs;
}; };
typedef Struct_(X8616_SerializeInfo) { typedef Struct_(X8616_SerializeInfo) {
Str8 text; X8616_InfoList msgs;
U4 instructions_written; Str8 text;
X8616_SerializeStatus status; U4 instructions_written;
byte_pad(4);
}; };
X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request); X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request);
-34
View File
@@ -55,7 +55,6 @@ Standard: c23
#define LP_ static // static data within procedure scope #define LP_ static // static data within procedure scope
#define internal static // internal #define internal static // internal
#define attribute(directive) __attribute__((directive)) #define attribute(directive) __attribute__((directive))
#define asm __asm__ #define asm __asm__
@@ -74,39 +73,6 @@ Standard: c23
#define R_ restrict #define R_ restrict
#define V_ volatile #define V_ volatile
// R_ (restrict) establishes an "Eigen" or "Proprius" mapping.
// Unlike volatile (V_), which assumes the memory can be changed by anything,
// R_ tells the compiler that this pointer holds the *sole*, private (idios) ownership of the memory slice.
// Writes to this memory are exclusively bound to this single symbolic mapping for the duration of the scope, guaranteeing zero aliasing.
#pragma region Fictional //, used for intiution
#define EUB_ restrict // Execute Unit Bound: Data is siloed in the ALU Register File. The Load/Store Unit is bypassed. (Route to Execution Unit. Keep in registers)
#define ISO_ restrict // Isolated Provenance: Alternative to Exu_. Guarantees electrical memory isolation,
// unlocking the compilers ability to safely pack data across multiple parallel SIMD lanes (vectorization).
#define LSU_ volatile // Load/Store Unit Bound: The compiler is forbidden from caching in registers. Forces physical L1 Cache matrix sampling.
#define LIVE_ volatile // Live External Data: Alternative to Lsu_ emphasizing the memory is tapped by an external electrical actor.
#define latch_store /* ~: atomic_store*/ // Blasts voltages from the Store Buffer into the L1 SRAM, physically flipping the cross-coupled inverters to lock the state.
#define pulse_rfo /* ~: atomic_xchg*/ // Broadcasts an electrical RFO (Request For Ownership) pulse across the CPU mesh network to invalidate other L1 caches.
#define tact_acquire /* ~: memory_order_acquire*/ // Clamp. Sends a voltage signal to the instruction decoder to halt the Out-of-Order engine until the load resolves.
#define tact_release /* ~: memory_order_release*/ // Drain. Forces the Store Buffer flip-flops to completely empty into the L1 cache before proceeding.
// -----------------------------------------------------------------------------
// Out-of-Order (OoO) Pipeline Modifiers
// -----------------------------------------------------------------------------
#define ooo_drift_ __ATOMIC_RELAXED // OoO engine allowed to drift
#define ooo_anchor_ __ATOMIC_ACQUIRE // Anchor the Load Queue (halt spec lookahead)
#define ooo_drain_ __ATOMIC_RELEASE // Drain the Store Buffer (force writeback)
#define ooo_weld_ __ATOMIC_SEQ_CST // Weld pipeline (total order bus lock)
// Latch operations with physical queue modifiers
#define latch_load_anchor(ptr) //__atomic_load_n(ptr, ooo_anchor_)
#define latch_store_drain(ptr, val) //__atomic_store_n(ptr, val, ooo_drain_)
#define pulse_xchg_weld(ptr, val) //__atomic_exchange_n(ptr, val, ooo_weld_)
#pragma endregion Fictional
#define r_(ptr) C_(T_(ptr[0])*R_, ptr) // Constrain pointer to restrict #define r_(ptr) C_(T_(ptr[0])*R_, ptr) // Constrain pointer to restrict
#define v_(ptr) C_(T_(ptr[0])V_*, ptr) // #define v_(ptr) C_(T_(ptr[0])V_*, ptr) //
#define tr_(type, ptr) C_(type *R_, ptr) #define tr_(type, ptr) C_(type *R_, ptr)
+8 -6
View File
@@ -99,11 +99,11 @@ int main()
Slice_X8616_DecodedInstruction decoded = farena_push_array(& decode_arena, X8616_DecodedInstruction, data.len); Slice_X8616_DecodedInstruction decoded = farena_push_array(& decode_arena, X8616_DecodedInstruction, data.len);
X8616_DecodeInfo info = x8616_decode_( X8616_DecodeInfo info = x8616_decode_(
.source = data.ptr, .source = data.ptr,
.source_size = data.len, .source_len = data.len,
.instructions = decoded.ptr, .out_instructions = decoded.ptr,
.instruction_capacity = decoded.len, .instruction_cap = decoded.len,
.info_arena = & decode_arena, .info_arena = & decode_arena,
); );
if (info.source_consumed != data.len || info.instruction_count == 0 || info.msgs.error_count || info.msgs.dropped_count) { if (info.source_consumed != data.len || info.instruction_count == 0 || info.msgs.error_count || info.msgs.dropped_count) {
ms_exit_process(10); ms_exit_process(10);
@@ -114,8 +114,10 @@ int main()
.instruction_count = info.instruction_count, .instruction_count = info.instruction_count,
.output = slice_ut_arr(smem.text_mem), .output = slice_ut_arr(smem.text_mem),
.scratch = slice_ut_arr(smem.Scratchpad), .scratch = slice_ut_arr(smem.Scratchpad),
.info_arena = & decode_arena,
.msgs = & info.msgs,
}); });
if (text.status != x8616_serialize_ok || text.instructions_written != info.instruction_count) { if (text.msgs.error_count || text.msgs.dropped_count || text.instructions_written != info.instruction_count) {
ms_exit_process(13); ms_exit_process(13);
return 13; return 13;
} }