mirror of
https://github.com/Ed94/perfaware.git
synced 2026-09-14 03:39:23 +00:00
progress
This commit is contained in:
+44
-43
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+67
-25
@@ -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)
|
||||||
{
|
{
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 compiler’s 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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user