Compare commits

Author SHA1 Message Date
ed b9b1ed460a Better str8_fmt_ktl_buf (using simd) 2026-09-08 20:45:57 -04:00
ed 749a712ceb update comment 2026-09-08 15:32:40 -04:00
ed 7e533cbfb2 fixes, convering x8616_decode_gen_emit_plan to use formatting template. 2026-09-08 13:42:59 -04:00
ed 28e6e38c92 decoder table generator (metaprogram) works... will test rest tmrw. 2026-09-05 00:03:12 -04:00
ed 6a456097ba decoder 2026-09-04 22:24:45 -04:00
ed bfd02f4472 misc changes, preparing for 8086 module. 2026-09-04 21:02:31 -04:00
ed aa9c4d48f6 starting to prep to decode instructions 2026-08-07 10:01:20 -04:00
ed 823ec3d499 Add update_deps.ps1 (clone computer enhance repo) 2026-08-07 01:32:51 -04:00
ed 77bda7741f Picture! 2026-08-07 01:08:26 -04:00
ed 8b4c8a2c71 got file reading working for the binary. 2026-08-07 01:06:57 -04:00
ed 6feff68b33 Some more prep 2026-08-06 21:10:04 -04:00
ed ac1fffa422 flag catalogue 2026-08-06 19:17:52 -04:00
ed 030876da48 working build. (not run) 2026-08-06 19:04:14 -04:00
ed 8b3e6f5ef3 wip: rusty with the build scripts 2026-08-06 17:08:56 -04:00
ed ce3206393a fix for str8gen_append_str8 2026-08-06 16:38:11 -04:00
ed 008d5e12b3 build.ps1 skeleton 2026-08-06 16:33:42 -04:00
ed b09b51fdf5 add gencpp c11 as dependency 2026-08-06 16:33:23 -04:00
ed 154c85f253 vs code setup 2026-08-06 16:33:09 -04:00
ed f49fcbe510 boostrap duffle (not compiled, unverified) 2026-08-06 16:33:00 -04:00
ed 31f81ec8e3 lua 2026-08-06 14:35:35 -04:00
ed f116f02503 Starter stuff 2026-08-06 14:18:09 -04:00
ed 57154dc801 Wiping repo clean, starting anew 2026-08-06 14:04:18 -04:00
60 changed files with 35200 additions and 20078 deletions
+34 -3
View File
@@ -1,11 +1,42 @@
[*.md]
root = true
[*.s]
indent_style = tab
indent_size = 2
[*.asm]
indent_style = tab
indent_size = 2
[*.refactor]
indent_style = space
indent_size = 4
[*.md]
indent_style = space
indent_size = 4
[*.h]
indent_style = tab
indent_size = 2
[*.c]
indent_style = tab
indent_size = 4
indent_size = 2
[*.cpp]
[*.{ps1, psm1}]
indent_style = tab
indent_size = 4
[*.odin]
indent_style = tab
indent_size = 2
charset = utf-8
[*.{natvis, natstepfilter}]
indent_style = tab
indent_size = 4
[*.lua]
indent_style = tab
indent_size = 2
+3
View File
@@ -0,0 +1,3 @@
code/8086/* linguist-language=C
code/duffle/* linguist-language=C
code/part_1/* linguist-language=C
+2
View File
@@ -0,0 +1,2 @@
build
course_content
+12 -7
View File
@@ -1,19 +1,24 @@
{
"configurations": [
{
"name": "Win32",
"name": "The Usual (clang)",
"includePath": [
"${workspaceFolder}/**"
"${workspaceFolder}/code/",
"${workspaceFolder}/code/8086",
"${workspaceFolder}/code/duffle",
"${workspaceFolder}/code/part_1"
],
"defines": [
"_DEBUG",
"BUILD_DEBUG",
"UNICODE",
"_UNICODE"
"_UNICODE",
"INTELLISENSE_DIRECTIVES"
],
"windowsSdkVersion": "10.0.22621.0",
"compilerPath": "cl.exe",
"compileCommands": "${workspaceFolder}/part_1/build/compile_commands.json"
"compilerPath": "clang",
"cStandard": "c11",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
}
-19
View File
@@ -1,19 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceRoot}/part_1/build/sim_8086.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}/part_1",
"environment": [],
"console": "externalTerminal"
}
]
}
+2 -8
View File
@@ -1,9 +1,3 @@
{
"files.associations": {
"*.rmd": "markdown",
"zpl.h": "c",
"cstddef": "cpp",
"xtr1common": "cpp",
"*.inline": "cpp"
}
}
"C_Cpp.default.compilerPath": "C:\\Program Files\\LLVM\\bin\\clang.exe",
}
-51
View File
@@ -1,51 +0,0 @@
#include "bloat.hpp"
namespace Op
{
enum Code : u8
{
#define D_Entry( Entry_ ) Entry,
#include "opcodes.inline"
Num,
#undef D_Entry
};
char const* str( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* meumonic( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.meumonics.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* intuitive( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.intuitive.inline"
#undef D_Entry
};
return code_to_str[ Num];
}
}
-146
View File
@@ -1,146 +0,0 @@
D_Entry( add_00 )
D_Entry( add_01 )
D_Entry( add_02 )
D_Entry( add_04 )
D_Entry( add_05 )
D_Entry( push_06 )
D_Entry( pop_07 )
D_Entry( or_10 )
D_Entry( or_11 )
D_Entry( or_12 )
D_Entry( or_13 )
D_Entry( or_14 )
D_Entry( or_15 )
D_Entry( push_16 )
D_Entry( _17 )
D_Entry( adc_20 )
D_Entry( adc_21 )
D_Entry( adc_22 )
D_Entry( adc_23 )
D_Entry( adc_24 )
D_Entry( adc_25 )
D_Entry( push_26 )
D_Entry( pop_27 )
D_Entry( sbb_30 )
D_Entry( sbb_31 )
D_Entry( sbb_32 )
D_Entry( sbb_33 )
D_Entry( sbb_34 )
D_Entry( sbb_35 )
D_Entry( push_36 )
D_Entry( pop_37 )
D_Entry( and_40 )
D_Entry( and_41 )
D_Entry( and_42 )
D_Entry( and_43 )
D_Entry( and_44 )
D_Entry( and_45 )
D_Entry( es_46 )
D_Entry( daa_47 )
D_Entry( sub_50 )
D_Entry( sub_51 )
D_Entry( sub_52 )
D_Entry( sub_53 )
D_Entry( sub_54 )
D_Entry( sub_55 )
D_Entry( cs_56 )
D_Entry( das_57 )
D_Entry( xor_60 )
D_Entry( xor_61 )
D_Entry( xor_62 )
D_Entry( xor_63 )
D_Entry( xor_64 )
D_Entry( xor_65 )
D_Entry( ss_66 )
D_Entry( aaa_67 )
D_Entry( cmp_70 )
D_Entry( cmp_71 )
D_Entry( cmp_72 )
D_Entry( cmp_73 )
D_Entry( cmp_74 )
D_Entry( cmp_75 )
D_Entry( ds_75 )
D_Entry( ds_76 )
D_Entry( aas_107 )
D_Entry( inc_100 )
D_Entry( inc_101 )
D_Entry( inc_102 )
D_Entry( inc_103 )
D_Entry( inc_104 )
D_Entry( inc_105 )
D_Entry( inc_106 )
D_Entry( inc_107 )
D_Entry( dec_100 )
D_Entry( dec_101 )
D_Entry( dec_102 )
D_Entry( dec_103 )
D_Entry( dec_104 )
D_Entry( dec_105 )
D_Entry( dec_106 )
D_Entry( dec_107 )
D_Entry( push_110 )
D_Entry( push_111 )
D_Entry( push_112 )
D_Entry( push_113 )
D_Entry( push_114 )
D_Entry( push_115 )
D_Entry( push_116 )
D_Entry( push_117 )
D_Entry( pop_120 )
D_Entry( pop_121 )
D_Entry( pop_122 )
D_Entry( pop_123 )
D_Entry( pop_124 )
D_Entry( pop_125 )
D_Entry( pop_126 )
D_Entry( pop_127 )
D_Entry( pop_130 )
D_Entry( pop_131 )
D_Entry( pop_132 )
D_Entry( pop_133 )
D_Entry( pop_134 )
D_Entry( pop_135 )
D_Entry( pop_136 )
D_Entry( pop_137 )
D_Entry( _140 )
D_Entry( _141 )
D_Entry( _142 )
D_Entry( _143 )
D_Entry( _144 )
D_Entry( _145 )
D_Entry( _146 )
D_Entry( _147 )
D_Entry( _150 )
D_Entry( _151 )
D_Entry( _152 )
D_Entry( _153 )
D_Entry( _154 )
D_Entry( _155 )
D_Entry( _156 )
D_Entry( _157 )
D_Entry( jo_160 )
D_Entry( jno_161 )
D_Entry( jb_jnae_jc_162 )
D_Entry( jnb_jae_jnc_163 )
D_Entry( je_jz_164 )
D_Entry( jne_jnz_165 )
D_Entry( jbe_jna_166 )
D_Entry( jnbe_ja_167 )
D_Entry( js_170 )
D_Entry( jns_171 )
D_Entry( jp_jpe_172 )
D_Entry( jnp_jpo_173 )
D_Entry( jl_jnge_174 )
D_Entry( jnl_jge_175 )
D_Entry( jle_jng_176 )
D_Entry( jnle_jg_177 )
D_Entry( add_200 )
D_Entry( or_201 )
D_Entry( adc_201 )
D_Entry( sbb_202 )
D_Entry( sub_203 )
D_Entry( cmp_204 )
D_Entry( add_205 )
D_Entry( adc_206 )
D_Entry( sbb_207 )
D_Entry( sub_210 )
View File
View File
-16
View File
@@ -1,16 +0,0 @@
# perfaware
Homework for Casey's [Performance Aware Programming course](https://www.computerenhance.com/p/table-of-contents)
[Material Source](https://github.com/cmuratori/computer_enhance)
Thirdparty Libraries:
* [zpl](https://github.com/zpl-c) - Used instead of the C/C++ standard library.
Tools:
* [scoop](https://scoop.sh) : Windows package manager
* clang : C/C++ compiler
```scoop install llvm```
* meson : Build system
```scoop install meson```
* nasm : x86 Assembler
```scoop install nasm```
+16
View File
@@ -0,0 +1,16 @@
# Computer Enhance: Performance Aware Programming Course
Progressing with company team.
Disable latency of submodules:
```ps1
git -C . config --local diff.ignoreSubmodules all
git -C . config --local status.submoduleSummary false
git -C . config --local submodule.recurse false
```
## Gallery
Part 1: File read!
![Part 1: File read!](./docs/assets/raddbg_2026-08-07_01-06-36.png)
+458
View File
@@ -0,0 +1,458 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "encoder.h"
# include "info.h"
# include "decoder.h"
# include "gen/decoder_table.h"
#endif
RO_ global U1 x8616_decode_disp_bytes[32] = {
0,0,0,0,0,0,2,0,
1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,
0,0,0,0,0,0,0,0,
};
RO_ global U1 x8616_decode_payload_bytes[] = {
0, // none
0, // imm: dynamic
1, // imm8
2, // imm16
2, // mem-direct
1, // rel8
2, // rel16
4, // far-ptr
};
typedef Struct_(X8616_DecodePlex) {
U1 const* source;
U4 source_size;
U4 source_offset;
U1 body[X8616_DECODE_BODY_CAP + X8616_DECODE_BODY_PAD];
U1 body_available;
U2 dispatch;
U1 plan_idx;
X8616_DecodePlan const* plan;
U1 opcode;
U1 post_opcode;
U1 mod_rm;
U1 d;
U1 w;
U1 s;
U1 v;
U1 z;
U1 reg_opcode;
U1 sr_opcode;
U1 mod;
U1 reg;
U1 rm;
U1 sr_modrm;
X8616_WidthMode width;
U1 body_at;
U1 displacement_at;
U1 displacement_bytes;
U1 payload_at;
U1 payload_bytes;
U1 body_required;
S2 displacement;
U2 direct_address;
U2 payload_u16;
U2 far_segment;
B1 direct_memory;
B1 classification_truncated;
B1 encoding_invalid;
X8616_DecodedPrefixes prefixes;
X8616_DecodedOperand operand_source[X8616_OPERAND_SOURCE_COUNT];
X8616_DecodedInstruction instruction;
FArena* info_arena;
X8616_InfoList* msgs;
};
FI_ U2 x8616_decode_u2(U1_R bytes) { return C_(U2, bytes[0] | u2_(bytes[1] << 8)); }
internal void
x8616_decode_apply_prefix(X8616_DecodePlex_R plex, X8616_DecodePlan_R plan, U1 opcode) {
plex->prefixes.count += 1;
plex->prefixes.lock |= plan->prefix_kind == x8616_prefix_lock;
if (plan->prefix_kind == x8616_prefix_repeat) {
plex->prefixes.has_repeat = 1;
plex->prefixes.repeat = (opcode >> plan->z_shift) & 0b1;
}
if (plan->prefix_kind == x8616_prefix_segment) {
plex->prefixes.has_segment = 1;
plex->prefixes.segment = (opcode >> plan->sr_shift) & 0b11;
}
}
internal U4
x8616_decode_one_plex(X8616_DecodePlex* plex)
{
U4 prefix_at = 0;
// Prefix pass. Ambiguous/group opcodes are never prefixes, so only direct
// dispatch entries participate in this loop.
while (prefix_at < plex->source_size)
{
U1 prefix_opcode = plex->source[prefix_at];
U2 prefix_dispatch = x8616_decode_dispatch[prefix_opcode];
if (prefix_dispatch == false || (prefix_dispatch & X8616_DECODE_AUX_BIT)) break;
X8616_DecodePlan const* prefix_plan = x8616_decode_plans + prefix_dispatch;
if ((prefix_plan->flags & x8616_plan_is_prefix) == false) break;
x8616_decode_apply_prefix(plex, prefix_plan, prefix_opcode);
++ prefix_at;
}
U4 body_source_size = plex->source_size - prefix_at;
plex->body_available = u1_(body_source_size < X8616_DECODE_BODY_CAP ? body_source_size : X8616_DECODE_BODY_CAP);
for (U1 idx = 0; idx < plex->body_available; ++ idx) plex->body[idx] = plex->source[prefix_at + idx];
plex->opcode = plex->body[0];
plex->dispatch = x8616_decode_dispatch[plex->opcode];
if (body_source_size == 0) {
plex->classification_truncated = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_truncated_instruction
, plex->source_offset + prefix_at
, 0
, 1
, 0
);
}
else if (plex->dispatch & X8616_DECODE_AUX_BIT)
{
if (body_source_size < 2) {
plex->classification_truncated = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_truncated_instruction
, plex->source_offset + prefix_at
, u2_(body_source_size)
, 2
, body_source_size
);
}
else
{
U2 aux_base = plex->dispatch & X8616_DECODE_AUX_MASK;
plex->plan_idx = x8616_decode_aux[aux_base + plex->body[1]];
if (plex->plan_idx == false) {
plex->encoding_invalid = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_invalid_opcode_extension
, plex->source_offset + prefix_at
, 2
, 0
, plex->body[1]
);
}
}
}
else
{
plex->plan_idx = C_(U1, plex->dispatch);
if (plex->plan_idx == 0) {
plex->encoding_invalid = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_invalid_opcode
, plex->source_offset + prefix_at
, 1
, 0
, plex->opcode
);
}
}
plex->plan = x8616_decode_plans + plex->plan_idx;
// A direct-dispatch plan may still have a constrained second byte.
// Group opcodes with multiple candidates were already resolved through aux.
if (plex->plan_idx && (plex->plan->flags & (x8616_plan_has_modrm | x8616_plan_has_post_opcode)))
{
if (body_source_size < 2)
{
if (plex->classification_truncated == 0) {
plex->classification_truncated = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_truncated_instruction
, plex->source_offset + prefix_at
, u2_(body_source_size)
, 2
, body_source_size
);
}
}
else
{
U1 second = plex->body[1];
if (plex->plan->mod_rm.mask && (second & plex->plan->mod_rm.mask) != plex->plan->mod_rm.bits) {
plex->encoding_invalid = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_invalid_opcode_extension
, plex->source_offset + prefix_at + 1
, 1
, plex->plan->mod_rm.bits
, second & plex->plan->mod_rm.mask
);
}
if (plex->plan->post_opcode.mask && (second & plex->plan->post_opcode.mask) != plex->plan->post_opcode.bits) {
plex->encoding_invalid = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_invalid_post_opcode
, plex->source_offset + prefix_at + 1
, 1
, plex->plan->post_opcode.bits
, second & plex->plan->post_opcode.mask
);
}
}
}
// Nil plan: still return a normal zero-valued instruction record and make
// progress through the stream. Aux classification inspected two bytes.
if (plex->plan_idx == 0) {
U1 invalid_body_size = (plex->dispatch & X8616_DECODE_AUX_BIT) && body_source_size >= 2 ? 2 : u1_(body_source_size != 0);
plex->instruction.prefixes = plex->prefixes;
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.opcode = plex->opcode;
plex->instruction.size = u1_(prefix_at + invalid_body_size);
plex->instruction.size_required = plex->instruction.size;
return plex->instruction.size;
}
X8616_DecodePlan const* plan = plex->plan;
plex->d = (plex->opcode >> plan->d_shift) & 0b1;
plex->w = (plex->opcode >> plan->w_shift) & 0b1;
plex->s = (plex->opcode >> plan->s_shift) & 0b1;
plex->v = (plex->opcode >> plan->v_shift) & 0b1;
plex->z = (plex->opcode >> plan->z_shift) & 0b1;
plex->reg_opcode = (plex->opcode >> plan->reg_shift) & 0b111;
plex->sr_opcode = (plex->opcode >> plan->sr_shift) & 0b11;
plex->width = plan->width;
if (plex->width == x8616_width_dynamic && (plan->flags & x8616_plan_has_w))
plex->width = plex->w ? x8616_width_word : x8616_width_byte;
plex->body_at = 1;
if (plan->flags & x8616_plan_has_post_opcode) {
plex->post_opcode = plex->body[plex->body_at];
plex->body_at += 1;
}
if (plan->flags & x8616_plan_has_modrm) {
plex->mod_rm = plex->body[plex->body_at];
plex->mod = x8616_modrm_mod(plex->mod_rm);
plex->reg = x8616_modrm_reg(plex->mod_rm);
plex->rm = x8616_modrm_rm(plex->mod_rm);
plex->sr_modrm = x8616_modrm_sr(plex->mod_rm);
plex->body_at += 1;
}
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];
plex->direct_memory = (plan->flags & x8616_plan_uses_rm) && plex->mod == x8616_mod_mem && plex->rm == x8616_ea_direct;
if (plex->displacement_bytes == 1) plex->displacement = s2_(s1_(plex->body[plex->displacement_at]));
else if (plex->displacement_bytes == 2) plex->displacement = s2_(x8616_decode_u2(plex->body + plex->displacement_at));
if (plex->direct_memory) plex->direct_address = x8616_decode_u2(plex->body + plex->displacement_at);
plex->payload_at = plex->displacement_at + plex->displacement_bytes;
plex->payload_bytes = x8616_decode_payload_bytes[plan->payload];
if (plan->payload == x8616_payload_imm) {
plex->payload_bytes = (plex->width == x8616_width_word && ((plan->flags & x8616_plan_has_s) && plex->s) == false) ? 2 : 1;
}
plex->body_required = plex->payload_at + plex->payload_bytes;
plex->payload_u16 = x8616_decode_u2(plex->body + plex->payload_at);
plex->far_segment = x8616_decode_u2(plex->body + plex->payload_at + 2);
if (body_source_size < plex->body_required && plex->classification_truncated == 0) {
plex->classification_truncated = 1;
x8616_info_push(plex->info_arena, plex->msgs, x8616_info_error
, x8616_info_truncated_instruction
, plex->source_offset + prefix_at
, u2_(body_source_size)
, plex->body_required, body_source_size);
}
// ------------------------------------------------------------------------
// Operand-source plex
//
// Every possible operand source is populated once from the shared decoded
// fields. The plan projects two slots out of this array; there is no
// operand-kind switch on the hot path.
X8616_DecodedOperand* source = plex->operand_source;
source[x8616_operand_reg_modrm].flags = x8616_decoded_operand_register;
source[x8616_operand_reg_modrm].width = plex->width;
source[x8616_operand_reg_modrm].reg = plex->reg;
source[x8616_operand_reg_opcode].flags = x8616_decoded_operand_register;
source[x8616_operand_reg_opcode].width = plex->width;
source[x8616_operand_reg_opcode].reg = plex->reg_opcode;
source[x8616_operand_segment_modrm].flags = x8616_decoded_operand_segment;
source[x8616_operand_segment_modrm].width = x8616_width_word;
source[x8616_operand_segment_modrm].segment = plex->sr_modrm;
source[x8616_operand_segment_opcode].flags = x8616_decoded_operand_segment;
source[x8616_operand_segment_opcode].width = x8616_width_word;
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].width = plex->width;
source[x8616_operand_acc].reg = 0;
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].reg = x8616_dx;
source[x8616_operand_rm].width = plex->width;
if (plex->mod == x8616_mod_reg) {
source[x8616_operand_rm].flags = x8616_decoded_operand_register;
source[x8616_operand_rm].reg = plex->rm;
}
else {
source[x8616_operand_rm].flags = x8616_decoded_operand_memory;
source[x8616_operand_rm].mod = plex->mod;
source[x8616_operand_rm].ea = plex->rm;
source[x8616_operand_rm].displacement = plex->displacement;
source[x8616_operand_rm].displacement_bytes = plex->displacement_bytes;
if (plex->direct_memory) {
source[x8616_operand_rm].flags |= x8616_decoded_operand_direct;
source[x8616_operand_rm].address = plex->direct_address;
}
}
source[x8616_operand_imm].flags = x8616_decoded_operand_immediate
| (((plan->flags & x8616_plan_has_s) && plex->s) ? x8616_decoded_operand_sign_extended : 0);
source[x8616_operand_imm].width = plex->width;
source[x8616_operand_imm].immediate = plex->payload_u16;
source[x8616_operand_imm].immediate_bytes = plex->payload_bytes;
source[x8616_operand_imm8].flags = x8616_decoded_operand_immediate;
source[x8616_operand_imm8].width = x8616_width_byte;
source[x8616_operand_imm8].immediate = C_(U1, plex->payload_u16);
source[x8616_operand_imm8].immediate_bytes = 1;
source[x8616_operand_imm16].flags = x8616_decoded_operand_immediate;
source[x8616_operand_imm16].width = x8616_width_word;
source[x8616_operand_imm16].immediate = plex->payload_u16;
source[x8616_operand_imm16].immediate_bytes = 2;
source[x8616_operand_mem_direct].flags = x8616_decoded_operand_memory | x8616_decoded_operand_direct;
source[x8616_operand_mem_direct].width = plex->width;
source[x8616_operand_mem_direct].address = plex->payload_u16;
source[x8616_operand_rel8].flags = x8616_decoded_operand_relative;
source[x8616_operand_rel8].width = x8616_width_byte;
source[x8616_operand_rel8].displacement = C_(S2, C_(S1, plex->payload_u16));
source[x8616_operand_rel8].displacement_bytes = 1;
source[x8616_operand_rel16].flags = x8616_decoded_operand_relative;
source[x8616_operand_rel16].width = x8616_width_word;
source[x8616_operand_rel16].displacement = C_(S2, plex->payload_u16);
source[x8616_operand_rel16].displacement_bytes = 2;
source[x8616_operand_far_ptr].flags = x8616_decoded_operand_far_ptr;
source[x8616_operand_far_ptr].far_offset = plex->payload_u16;
source[x8616_operand_far_ptr].far_segment = plex->far_segment;
source[x8616_operand_shift_count].flags = x8616_decoded_operand_implicit;
source[x8616_operand_shift_count].width = x8616_width_byte;
if (plex->v == x8616_v_cl) {
source[x8616_operand_shift_count].flags |= x8616_decoded_operand_register;
source[x8616_operand_shift_count].reg = x8616_cl;
}
else {
source[x8616_operand_shift_count].flags |= x8616_decoded_operand_immediate;
source[x8616_operand_shift_count].immediate = 1;
source[x8616_operand_shift_count].immediate_bytes = 0;
}
// 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);
plex->instruction.operands[swap] = source[plan->operands[0]];
plex->instruction.operands[swap ^ 1] = source[plan->operands[1]];
plex->instruction.op = plan->op;
plex->instruction.flags = plan->encoding_flags;
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.prefixes = plex->prefixes;
plex->instruction.operand_count = plan->operand_count;
plex->instruction.opcode = plex->opcode;
plex->instruction.mod_rm = plex->mod_rm;
plex->instruction.has_mod_rm = (plan->flags & x8616_plan_has_modrm) != 0;
U4 total_required = prefix_at + plex->body_required;
U4 total_available = plex->source_size;
U4 total_consumed = total_required < total_available ? total_required : total_available;
plex->instruction.size = u1_(total_consumed);
plex->instruction.size_required = u1_(total_required);
return total_consumed;
}
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request)
{
X8616_DecodeInfo result = {0};
result.instruction_capacity = request.instruction_capacity;
while (result.source_consumed < request.source_size && result.instruction_count < request.instruction_capacity) {
X8616_DecodePlex plex = {0};
plex.source = request.source + result.source_consumed;
plex.source_size = request.source_size - result.source_consumed;
plex.source_offset = result.source_consumed;
plex.info_arena = request.info_arena;
plex.msgs = & result.msgs;
U4 consumed = x8616_decode_one_plex(& plex);
request.instructions[result.instruction_count++] = plex.instruction;
if (consumed == false) consumed = 1;
result.source_consumed += consumed;
}
if (result.source_consumed < request.source_size && result.instruction_count == request.instruction_capacity) {
x8616_info_push(request.info_arena, & result.msgs, x8616_info_warning
, x8616_info_output_full
, result.source_consumed
, 0
, request.instruction_capacity
, result.instruction_count
);
}
return result;
}
X8616_DecodeOneInfo x8616_decode_one(U1_R source, U4 source_size, FArena_R info_arena) {
X8616_DecodeOneInfo result = {0};
X8616_DecodePlex plex = {0};
plex.source = source;
plex.source_size = source_size;
plex.source_offset = 0;
plex.info_arena = info_arena;
plex.msgs = & result.msgs;
result.source_consumed = x8616_decode_one_plex(& plex);
result.instruction = plex.instruction;
return result;
}
+163
View File
@@ -0,0 +1,163 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "encoder.h"
# include "info.h"
#endif
enum {
X8616_OPERAND_SOURCE_COUNT = 0x10,
X8616_DECODE_BODY_CAP = 0x06,
X8616_DECODE_BODY_PAD = 0x02,
};
typedef Enum_(U2, X8616_DecodedOperandFlags) {
x8616_decoded_operand_none = 0b0000000000000000,
x8616_decoded_operand_register = 0b0000000000000001,
x8616_decoded_operand_segment = 0b0000000000000010,
x8616_decoded_operand_memory = 0b0000000000000100,
x8616_decoded_operand_immediate = 0b0000000000001000,
x8616_decoded_operand_relative = 0b0000000000010000,
x8616_decoded_operand_far_ptr = 0b0000000000100000,
x8616_decoded_operand_direct = 0b0000000001000000,
x8616_decoded_operand_sign_extended = 0b0000000010000000,
x8616_decoded_operand_implicit = 0b0000000100000000,
};
typedef Struct_(X8616_DecodedOperand) {
X8616_DecodedOperandFlags flags;
X8616_WidthMode width;
U1 reg;
U1 segment;
U1 mod;
U1 ea;
S2 displacement;
U2 address;
U2 immediate;
U2 far_offset;
U2 far_segment;
U1 displacement_bytes;
U1 immediate_bytes;
};
typedef Struct_(X8616_DecodedPrefixes) {
U1 count;
B1 lock;
B1 has_repeat;
X8616_Repeat repeat;
B1 has_segment;
X8616_Segment segment;
};
typedef Enum_(U1, X8616_DecodeFlags) {
x8616_decode_none = 0b00000000,
x8616_decode_invalid = 0b00000001,
x8616_decode_truncated = 0b00000010,
};
typedef Struct_(X8616_DecodedInstruction) {
X8616_Op op;
X8616_EncodingFlags flags;
X8616_DecodeFlags decode_flags;
X8616_WidthMode width;
X8616_DecodedPrefixes prefixes;
X8616_DecodedOperand operands[2];
U1 operand_count;
U1 opcode;
U1 mod_rm;
B1 has_mod_rm;
U1 size;
U1 size_required;
};
typedef Enum_(U2, X8616_DecodePlanFlags) {
x8616_plan_none = 0b0000000000000000,
x8616_plan_has_modrm = 0b0000000000000001,
x8616_plan_has_post_opcode = 0b0000000000000010,
x8616_plan_has_d = 0b0000000000000100,
x8616_plan_has_w = 0b0000000000001000,
x8616_plan_has_s = 0b0000000000010000,
x8616_plan_has_v = 0b0000000000100000,
x8616_plan_has_z = 0b0000000001000000,
x8616_plan_has_reg = 0b0000000010000000,
x8616_plan_has_sr = 0b0000000100000000,
x8616_plan_uses_rm = 0b0000001000000000,
x8616_plan_is_prefix = 0b0000010000000000,
};
typedef Enum_(U1, X8616_DecodePayload) {
x8616_payload_none = 0x0,
x8616_payload_imm = 0x1,
x8616_payload_imm8 = 0x2,
x8616_payload_imm16 = 0x3,
x8616_payload_mem_direct = 0x4,
x8616_payload_rel8 = 0x5,
x8616_payload_rel16 = 0x6,
x8616_payload_far_ptr = 0x7,
};
typedef Enum_(U1, X8616_DecodePrefixKind) {
x8616_prefix_none = 0x0,
x8616_prefix_lock = 0x1,
x8616_prefix_repeat = 0x2,
x8616_prefix_segment = 0x3,
};
typedef Struct_(X8616_DecodePlan) {
X8616_DecodePlanFlags flags;
X8616_Op op;
X8616_EncodingFlags encoding_flags;
X8616_WidthMode width;
X8616_Operand operands[2];
U1 operand_count;
X8616_DecodePayload payload;
X8616_DecodePrefixKind prefix_kind;
U1 d_shift;
U1 w_shift;
U1 s_shift;
U1 v_shift;
U1 z_shift;
U1 reg_shift;
U1 sr_shift;
X8616_BytePattern mod_rm;
X8616_BytePattern post_opcode;
};
enum {
X8616_DECODE_PLAN_INVALID = 0x00,
X8616_DECODE_AUX_BIT = 0x8000,
X8616_DECODE_AUX_MASK = 0x7FFF,
};
typedef Struct_(X8616_DecodeRequest) {
U1 const* source;
U4 source_size;
X8616_DecodedInstruction* instructions;
U4 instruction_capacity;
FArena* info_arena;
};
typedef Struct_(X8616_DecodeInfo) {
U4 source_consumed;
U4 instruction_count;
U4 instruction_capacity;
X8616_InfoList msgs;
};
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request);
typedef Struct_(X8616_DecodeOneInfo) {
X8616_DecodedInstruction instruction;
X8616_InfoList msgs;
U4 source_consumed;
};
X8616_DecodeOneInfo x8616_decode_one(U1_R source, U4 source_size, FArena_R info_arena);
+36
View File
@@ -0,0 +1,36 @@
#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 */
}
+412
View File
@@ -0,0 +1,412 @@
#include "duffle/dsl.h"
#include "duffle/asm.h"
#include "duffle/analysis.h"
#include "duffle/math.h"
#include "duffle/encoding.h"
#include "duffle/memory.h"
#include "duffle/hashing.h"
#include "duffle/tables.h"
#include "duffle/text.h"
#include "duffle/files.h"
#include "duffle/win32.h"
#include "info.h"
#include "encoder.h"
#include "encoder_table.h"
#include "decoder.h"
enum {
X8616_DECODE_GEN_MAX_AUX = X8616_DECODE_AUX_MASK + 1,
};
typedef Struct_(X8616_DecodeGen) {
X8616_DecodePlan plans[X8616_ENCODING_COUNT + 1];
U2 dispatch[256];
U1 aux[X8616_DECODE_GEN_MAX_AUX];
U4 aux_count;
U4 ambiguous_opcode_count;
U4 verified_count;
X8616_InfoList msgs;
};
typedef Struct_(X8616_DecodeGenInfo) {
U4 plan_count;
U4 aux_count;
U4 ambiguous_opcode_count;
U4 verified_count;
X8616_InfoList msgs;
};
FI_ B4 x8616_decode_gen_operand_uses_modrm(X8616_Operand operand) {
return operand == x8616_operand_rm || operand == x8616_operand_reg_modrm || operand == x8616_operand_segment_modrm;
}
FI_ B4 x8616_decode_gen_operand_uses_rm(X8616_Operand operand) { return operand == x8616_operand_rm; }
internal X8616_DecodePayload
x8616_decode_gen_payload_from_operand(X8616_Operand operand) {
switch (operand) {
case x8616_operand_imm: return x8616_payload_imm;
case x8616_operand_imm8: return x8616_payload_imm8;
case x8616_operand_imm16: return x8616_payload_imm16;
case x8616_operand_mem_direct: return x8616_payload_mem_direct;
case x8616_operand_rel8: return x8616_payload_rel8;
case x8616_operand_rel16: return x8616_payload_rel16;
case x8616_operand_far_ptr: return x8616_payload_far_ptr;
default: return x8616_payload_none;
}
}
internal X8616_DecodePrefixKind
x8616_decode_gen_prefix_kind(X8616_Encoding const* encoding) {
if ((encoding->flags & x8616_encoding_prefix) == 0) return x8616_prefix_none;
switch (encoding->op) {
case x8616_op_lock: return x8616_prefix_lock;
case x8616_op_rep: return x8616_prefix_repeat;
case x8616_op_segment: return x8616_prefix_segment;
default: return x8616_prefix_none;
}
}
internal X8616_DecodePlan
x8616_decode_gen_plan(X8616_Encoding const* encoding, U4 encoding_idx, X8616_InfoList* msgs, FArena_R info_scratch)
{
X8616_DecodePlan plan = {0};
plan.op = encoding->op;
plan.encoding_flags = encoding->flags;
plan.width = encoding->width;
plan.operands[0] = encoding->operands[0];
plan.operands[1] = encoding->operands[1];
plan.operand_count = (encoding->operands[0] != x8616_operand_none) + (encoding->operands[1] != x8616_operand_none);
plan.prefix_kind = x8616_decode_gen_prefix_kind(encoding);
plan.mod_rm = encoding->mod_rm;
plan.post_opcode = encoding->post_opcode;
if (encoding->mod_rm.mask || x8616_decode_gen_operand_uses_modrm(encoding->operands[0]) || x8616_decode_gen_operand_uses_modrm(encoding->operands[1]))
plan.flags |= x8616_plan_has_modrm;
if (encoding->post_opcode.mask)
plan.flags |= x8616_plan_has_post_opcode;
if (encoding->fields.d.width) { plan.flags |= x8616_plan_has_d; plan.d_shift = encoding->fields.d.shift; }
if (encoding->fields.w.width) { plan.flags |= x8616_plan_has_w; plan.w_shift = encoding->fields.w.shift; }
if (encoding->fields.s.width) { plan.flags |= x8616_plan_has_s; plan.s_shift = encoding->fields.s.shift; }
if (encoding->fields.v.width) { plan.flags |= x8616_plan_has_v; plan.v_shift = encoding->fields.v.shift; }
if (encoding->fields.z.width) { plan.flags |= x8616_plan_has_z; plan.z_shift = encoding->fields.z.shift; }
if (encoding->fields.reg.width) { plan.flags |= x8616_plan_has_reg; plan.reg_shift = encoding->fields.reg.shift; }
if (encoding->fields.sr.width) { plan.flags |= x8616_plan_has_sr; plan.sr_shift = encoding->fields.sr.shift; }
if (x8616_decode_gen_operand_uses_rm(encoding->operands[0]) || x8616_decode_gen_operand_uses_rm(encoding->operands[1]))
plan.flags |= x8616_plan_uses_rm;
if (encoding->flags & x8616_encoding_prefix)
plan.flags |= x8616_plan_is_prefix;
X8616_DecodePayload payload_0 = x8616_decode_gen_payload_from_operand(encoding->operands[0]);
X8616_DecodePayload payload_1 = x8616_decode_gen_payload_from_operand(encoding->operands[1]);
if (payload_0 && payload_1 && payload_0 != payload_1)
x8616_info_push(info_scratch, msgs, x8616_info_error, x8616_info_gen_multiple_payloads, encoding_idx, 0, payload_0, payload_1);
plan.payload = payload_0 ? payload_0 : payload_1;
U4 payload_max = 0;
switch (plan.payload) {
case x8616_payload_imm: payload_max = 2; break;
case x8616_payload_imm8: payload_max = 1; break;
case x8616_payload_imm16: payload_max = 2; break;
case x8616_payload_mem_direct: payload_max = 2; break;
case x8616_payload_rel8: payload_max = 1; break;
case x8616_payload_rel16: payload_max = 2; break;
case x8616_payload_far_ptr: payload_max = 4; break;
default: break;
}
U4 body_max = 1
+ ((plan.flags & x8616_plan_has_post_opcode) != 0)
+ ((plan.flags & x8616_plan_has_modrm) != 0)
+ ((plan.flags & x8616_plan_uses_rm) ? 2 : 0)
+ payload_max;
if (body_max > X8616_DECODE_BODY_CAP) x8616_info_push(info_scratch, msgs, x8616_info_error
, x8616_info_gen_body_cap_exceeded
, encoding_idx
, 0
, X8616_DECODE_BODY_CAP
, body_max
);
return plan;
}
FI_ B4 x8616_decode_gen_encoding_matches_opcode(X8616_Encoding const* encoding, U1 opcode) {
return (opcode & encoding->opcode.mask) == encoding->opcode.bits;
}
FI_ B4 x8616_decode_gen_plan_matches_second(X8616_DecodePlan const* plan, U1 byte) {
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;
return true;
}
internal void x8616_decode_gen_pass_plans(X8616_DecodeGen* gen, FArena_R info_scratch) {
for (U4 idx = 0; idx < X8616_ENCODING_COUNT; ++ idx)
gen->plans[idx + 1] = x8616_decode_gen_plan(x8616_encodings + idx, idx, & gen->msgs, info_scratch);
}
internal void
x8616_decode_gen_pass_dispatch(X8616_DecodeGen* gen, FArena_R info_scratch)
{
for (U4 opcode = 0; opcode < 256; ++ opcode)
{
U1 candidates[X8616_ENCODING_COUNT];
U4 candidate_count = 0;
for (U4 encoding_idx = 0; encoding_idx < X8616_ENCODING_COUNT; ++ encoding_idx)
if (x8616_decode_gen_encoding_matches_opcode(x8616_encodings + encoding_idx, C_(U1, opcode)))
candidates[candidate_count ++] = C_(U1, encoding_idx + 1);
if (candidate_count == 0) continue;
if (candidate_count == 1) { gen->dispatch[opcode] = candidates[0]; continue; }
if (gen->aux_count + 256 > X8616_DECODE_GEN_MAX_AUX) {
x8616_info_push(info_scratch, & gen->msgs, x8616_info_error
, x8616_info_gen_aux_cap_exceeded
, opcode
, 0
, X8616_DECODE_GEN_MAX_AUX
, gen->aux_count + 256
);
return;
}
U4 base = gen->aux_count;
gen->dispatch[opcode] = C_(U2, X8616_DECODE_AUX_BIT | base);
gen->aux_count += 256;
gen->ambiguous_opcode_count += 1;
for (U4 second = 0; second < 256; ++ second)
{
U1 selected = 0;
for (U4 candidate_idx = 0; candidate_idx < candidate_count; ++ candidate_idx)
{
U1 plan_idx = candidates[candidate_idx];
if (! x8616_decode_gen_plan_matches_second(gen->plans + plan_idx, C_(U1, second)))
continue;
if (selected) x8616_info_push(info_scratch, & gen->msgs, x8616_info_error
, x8616_info_gen_ambiguous_decode
, (opcode << 8) | second
, 0
, selected
, plan_idx
);
selected = plan_idx;
}
gen->aux[base + second] = selected;
}
}
}
internal void
x8616_decode_gen_pass_validate(X8616_DecodeGen* gen, FArena_R info_scratch)
{
for (U4 opcode = 0; opcode < 256; ++ opcode)
for (U4 second = 0; second < 256; ++ second)
{
U1 expected = 0;
for (U4 encoding_idx = 0; encoding_idx < X8616_ENCODING_COUNT; ++ encoding_idx)
{
X8616_Encoding const* encoding = x8616_encodings + encoding_idx;
if (x8616_decode_gen_encoding_matches_opcode(encoding, C_(U1, opcode)) == false) continue;
X8616_DecodePlan const* plan = gen->plans + encoding_idx + 1;
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
, x8616_info_gen_ambiguous_decode
, (opcode << 8) | second, 0
, expected, encoding_idx + 1
);
expected = C_(U1, encoding_idx + 1);
}
U2 dispatch = gen->dispatch[opcode];
U1 actual = 0;
if (dispatch & X8616_DECODE_AUX_BIT) {
U2 base = dispatch & X8616_DECODE_AUX_MASK;
actual = gen->aux[base + second];
}
else if (dispatch) {
U1 candidate = C_(U1, dispatch);
if (x8616_decode_gen_plan_matches_second(gen->plans + candidate, C_(U1, second)))
actual = candidate;
}
if (actual != expected) x8616_info_push(info_scratch, & gen->msgs, x8616_info_error
, x8616_info_gen_dispatch_mismatch
, (opcode << 8) | second, 0
, expected, actual
);
++ gen->verified_count;
}
}
X8616_DecodeGenInfo
x8616_decode_table_generate(X8616_DecodeGen* gen, FArena_R info_scratch) {
mem_zero_struct(gen[0]);
// gen[0] = (X8616_DecodeGen){0};
x8616_decode_gen_pass_plans (gen, info_scratch);
x8616_decode_gen_pass_dispatch(gen, info_scratch);
x8616_decode_gen_pass_validate(gen, info_scratch);
X8616_DecodeGenInfo result = {
.plan_count = X8616_ENCODING_COUNT + 1,
.aux_count = gen->aux_count,
.ambiguous_opcode_count = gen->ambiguous_opcode_count,
.verified_count = gen->verified_count,
.msgs = gen->msgs,
};
return result;
}
#define X8616_DECODE_TABLE_OUTPUT "./code/8086/gen/decoder_table.h"
enum {
INFO_MEMORY_SIZE = kilo(64),
TEXT_MEMORY_SIZE = kilo(128),
FILE_MEMORY_SIZE = kilo(4),
};
typedef FStack_(FStack_64k, U1, kilo(64));
typedef Struct_(SMemory) {
U1 info[INFO_MEMORY_SIZE];
U1 text[TEXT_MEMORY_SIZE];
U1 file[FILE_MEMORY_SIZE];
FStack_64k scratch;
X8616_DecodeGen gen;
};
global SMemory smem;
I_ void x8616_decode_gen_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);
Str8 text = str8_from_u4_buf(slice_ut_arr(buffer), value, radix, min_digits, 0, info);
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 x8616_decode_gen_append_hex_u2(Str8Gen_R out, U2 value) { x8616_decode_gen_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); }
FI_ Slice scratch_push(U8 len) { return fstack_push_(smem.scratch, len); }
typedef Opt_(str8_from_u4) { U4 radix, min_digits, digit_group_separator; };
I_ Str8 str8_from_u4_opt(U4 num, Opt_str8_from_u4 o) { if (o.radix == 0) {o.radix = 10;}
/*gather info*/Info_str8_from_u4 info = str8_from_u4_info(num, o.radix, o.min_digits, o.digit_group_separator);
/*write buf */return str8_from_u4_buf(scratch_push(128), num, o.radix, o.min_digits, o.digit_group_separator, info);
}
#define str8_from_u4(num, ...) str8_from_u4_opt(num, opt_(str8_from_u4, __VA_ARGS__))
#define code_str8(...) slit8(stringify(__VA_ARGS__))
internal void
x8616_decode_gen_emit_plan(Str8Gen_R out, X8616_DecodePlan_R plan) { defer_rewind(smem.scratch.top) {
Str8 template = code_str8(
\t{
<flags>, <op>, <encoding_flags>, <width>,
{<operands[0]>, <operands[1]>}, <operand_count>,
<payload>, <prefix_kind>,
<d_shift>, <w_shift>, <s_shift>, <v_shift>, <z_shift>, <reg_shift>, <sr_shift>,
{<mod_rm.bits>, <mod_rm.mask>},
{<post_opcode.bits>, <post_opcode.mask>},
},\n
);
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("op", hex_u1(plan->op)),
entry("encoding_flags", hex_u1(plan->encoding_flags)),
entry("width", hex_u1(plan->width)),
entry("operands[0]", hex_u1(plan->operands[0])),
entry("operands[1]", hex_u1(plan->operands[1])),
entry("operand_count", dec(plan->operand_count)),
entry("payload", dec(plan->payload)),
entry("prefix_kind", dec(plan->prefix_kind)),
entry("d_shift", dec(plan->d_shift)),
entry("w_shift", dec(plan->w_shift)),
entry("s_shift", dec(plan->s_shift)),
entry("v_shift", dec(plan->v_shift)),
entry("z_shift", dec(plan->z_shift)),
entry("reg_shift", dec(plan->reg_shift)),
entry("sr_shift", dec(plan->sr_shift)),
entry("mod_rm.bits", hex_u1(plan->mod_rm.bits)),
entry("mod_rm.mask", hex_u1(plan->mod_rm.mask)),
entry("post_opcode.bits", hex_u1(plan->post_opcode.bits)),
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));
}}
internal Str8
x8616_decode_gen_emit(Str8Gen_R out, X8616_DecodeGen_R gen) {
str8gen_append_str8(out, slit8(
"// Generated from encoder_table.h. Do not hand-edit.\n"
"// Plan 0 is the all-zero nil/invalid plan.\n\n"
"RO_ global X8616_DecodePlan x8616_decode_plans["));
x8616_decode_gen_append_dec(out, X8616_ENCODING_COUNT + 1);
str8gen_append_str8(out, slit8("] =\n{\n"));
for (U4 idx = 0; idx < X8616_ENCODING_COUNT + 1; ++ idx) x8616_decode_gen_emit_plan(out, gen->plans + idx);
str8gen_append_str8(out, slit8("};\n\nRO_ global U2 x8616_decode_dispatch[256] =\n{\n"));
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["));
x8616_decode_gen_append_dec(out, gen->aux_count);
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"));
x8616_decode_gen_append_hex_u1(out, gen->aux[idx]);
str8gen_append_str8(out, (idx & 15) == 15 ? slit8(",\n") : slit8(", "));
}
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);
}
int
main(void) {
FArena info_scratch = farena_make(slice_ut_arr(smem.info));
X8616_DecodeGenInfo gen_info = x8616_decode_table_generate(& smem.gen, & info_scratch);
if (gen_info.msgs.error_count) { ms_exit_process(1); return 1; }
Str8Gen output = str8gen_make(slice_ut_arr(smem.text));
Str8 generated = x8616_decode_gen_emit(& output, & smem.gen);
FArena file_scratch = farena_make(slice_ut_arr(smem.file));
B4 wrote = write_data_to_file_path(slit8(X8616_DECODE_TABLE_OUTPUT), generated, & file_scratch);
if (wrote == false) { ms_exit_process(2); return 2; }
if (gen_info.verified_count != 256 * 256) { ms_exit_process(3); return 3; }
ms_exit_process(0);
return 0;
}
+825
View File
@@ -0,0 +1,825 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "duffle/dsl.h"
#endif
typedef Struct_(X8616_BytePattern) { U1 bits; U1 mask; };
typedef Struct_(X8616_BitField) { U1 shift; U1 width; };
typedef Struct_(X8616_OpcodeFields) {
X8616_BitField d;
X8616_BitField w;
X8616_BitField s;
X8616_BitField v;
X8616_BitField z;
X8616_BitField reg;
X8616_BitField sr;
};
typedef Enum_(U1, X8616_Op) {
x8616_op_invalid = 0x00,
x8616_op_nop = 0x01,
x8616_op_mov = 0x02,
x8616_op_add = 0x03,
x8616_op_or = 0x04,
x8616_op_adc = 0x05,
x8616_op_sbb = 0x06,
x8616_op_and = 0x07,
x8616_op_sub = 0x08,
x8616_op_xor = 0x09,
x8616_op_cmp = 0x0A,
x8616_op_push = 0x0B,
x8616_op_pop = 0x0C,
x8616_op_xchg = 0x0D,
x8616_op_in = 0x0E,
x8616_op_out = 0x0F,
x8616_op_xlat = 0x10,
x8616_op_lea = 0x11,
x8616_op_lds = 0x12,
x8616_op_les = 0x13,
x8616_op_lahf = 0x14,
x8616_op_sahf = 0x15,
x8616_op_pushf = 0x16,
x8616_op_popf = 0x17,
x8616_op_inc = 0x18,
x8616_op_aaa = 0x19,
x8616_op_daa = 0x1A,
x8616_op_dec = 0x1B,
x8616_op_neg = 0x1C,
x8616_op_aas = 0x1D,
x8616_op_das = 0x1E,
x8616_op_mul = 0x1F,
x8616_op_imul = 0x20,
x8616_op_aam = 0x21,
x8616_op_div = 0x22,
x8616_op_idiv = 0x23,
x8616_op_aad = 0x24,
x8616_op_cbw = 0x25,
x8616_op_cwd = 0x26,
x8616_op_not = 0x27,
x8616_op_shl = 0x28,
x8616_op_shr = 0x29,
x8616_op_sar = 0x2A,
x8616_op_rol = 0x2B,
x8616_op_ror = 0x2C,
x8616_op_rcl = 0x2D,
x8616_op_rcr = 0x2E,
x8616_op_test = 0x2F,
x8616_op_rep = 0x30,
x8616_op_movs = 0x31,
x8616_op_cmps = 0x32,
x8616_op_scas = 0x33,
x8616_op_lods = 0x34,
x8616_op_stos = 0x35,
x8616_op_call = 0x36,
x8616_op_jmp = 0x37,
x8616_op_ret = 0x38,
x8616_op_retf = 0x39,
x8616_op_je = 0x3A,
x8616_op_jl = 0x3B,
x8616_op_jle = 0x3C,
x8616_op_jb = 0x3D,
x8616_op_jbe = 0x3E,
x8616_op_jp = 0x3F,
x8616_op_jo = 0x40,
x8616_op_js = 0x41,
x8616_op_jne = 0x42,
x8616_op_jnl = 0x43,
x8616_op_jg = 0x44,
x8616_op_jnb = 0x45,
x8616_op_ja = 0x46,
x8616_op_jnp = 0x47,
x8616_op_jno = 0x48,
x8616_op_jns = 0x49,
x8616_op_loop = 0x4A,
x8616_op_loopz = 0x4B,
x8616_op_loopnz = 0x4C,
x8616_op_jcxz = 0x4D,
x8616_op_int = 0x4E,
x8616_op_int3 = 0x4F,
x8616_op_into = 0x50,
x8616_op_iret = 0x51,
x8616_op_clc = 0x52,
x8616_op_cmc = 0x53,
x8616_op_stc = 0x54,
x8616_op_cld = 0x55,
x8616_op_std = 0x56,
x8616_op_cli = 0x57,
x8616_op_sti = 0x58,
x8616_op_hlt = 0x59,
x8616_op_wait = 0x5A,
x8616_op_lock = 0x5B,
x8616_op_segment = 0x5C,
};
typedef Enum_(U1, X8616_Operand) {
x8616_operand_none = 0x00,
x8616_operand_rm = 0x01,
x8616_operand_reg_modrm = 0x02,
x8616_operand_reg_opcode = 0x03,
x8616_operand_segment_modrm = 0x04,
x8616_operand_segment_opcode = 0x05,
x8616_operand_acc = 0x06,
x8616_operand_imm = 0x07,
x8616_operand_imm8 = 0x08,
x8616_operand_imm16 = 0x09,
x8616_operand_mem_direct = 0x0A,
x8616_operand_rel8 = 0x0B,
x8616_operand_rel16 = 0x0C,
x8616_operand_far_ptr = 0x0D,
x8616_operand_dx = 0x0E,
x8616_operand_shift_count = 0x0F,
};
typedef Enum_(U1, X8616_WidthMode) {
x8616_width_dynamic = 0x0,
x8616_width_byte = 0x1,
x8616_width_word = 0x2,
};
typedef Enum_(U1, X8616_EncodingFlags) {
x8616_encoding_none = 0b00000000,
x8616_encoding_far = 0b00000001,
x8616_encoding_prefix = 0b00000010,
};
/* mod_rm (Optional): Fixed constraint on the ModR/M byte.
post_opcode (Optional): Fixed byte immediately following the opcode.
fields: Variable fields carried by the opcode byte. width == 0: field is absent.
operands: Operand order describes d == 0.
If d exists and decodes to 1, operands[0] and operands[1] are swapped.
width: Explicit width only when the encoding has no w field.
flags: Encoding metadata not represented by an explicit operand. */
typedef Struct_(X8616_Encoding) {
X8616_BytePattern opcode;
X8616_BytePattern mod_rm;
X8616_BytePattern post_opcode;
X8616_OpcodeFields fields;
X8616_Operand operands[2];
X8616_WidthMode width;
X8616_EncodingFlags flags;
X8616_Op op;
};
typedef Enum_(U1, X8616_Width) {
x8616_w_byte = 0b0,
x8616_w_word = 0b1,
};
typedef Enum_(U1, X8616_Direction) {
x8616_d_rm_dst = 0b0,
x8616_d_reg_dst = 0b1,
x8616_d_acc_dst = 0b0,
x8616_d_mem_dst = 0b1,
x8616_d_seg_dst = 0b1,
};
typedef Enum_(U1, X8616_Sign) {
x8616_s_full = 0b0,
x8616_s_extend = 0b1,
};
typedef Enum_(U1, X8616_VariableShift) {
x8616_v_one = 0b0,
x8616_v_cl = 0b1,
};
typedef Enum_(U1, X8616_Repeat) {
x8616_repne = 0b0,
x8616_rep = 0b1,
};
typedef Enum_(U1, X8616_Mod) {
x8616_mod_mem = 0b00,
x8616_mod_mem_d8 = 0b01,
x8616_mod_mem_d16 = 0b10,
x8616_mod_reg = 0b11,
};
typedef Enum_(U1, X8616_Reg8) {
x8616_al = 0b000,
x8616_cl = 0b001,
x8616_dl = 0b010,
x8616_bl = 0b011,
x8616_ah = 0b100,
x8616_ch = 0b101,
x8616_dh = 0b110,
x8616_bh = 0b111,
};
typedef Enum_(U1, X8616_Reg16) {
x8616_ax = 0b000,
x8616_cx = 0b001,
x8616_dx = 0b010,
x8616_bx = 0b011,
x8616_sp = 0b100,
x8616_bp = 0b101,
x8616_si = 0b110,
x8616_di = 0b111,
};
typedef Enum_(U1, X8616_Segment) {
x8616_es = 0b00,
x8616_cs = 0b01,
x8616_ss = 0b10,
x8616_ds = 0b11,
};
typedef Enum_(U1, X8616_EA) {
x8616_ea_bx_si = 0b000,
x8616_ea_bx_di = 0b001,
x8616_ea_bp_si = 0b010,
x8616_ea_bp_di = 0b011,
x8616_ea_si = 0b100,
x8616_ea_di = 0b101,
x8616_ea_bp = 0b110, // mod 01/10
x8616_ea_direct = 0b110, // mod 00
x8616_ea_bx = 0b111,
};
typedef Enum_(U1, X8616_ALU) {
x8616_add = 0b000,
x8616_or = 0b001,
x8616_adc = 0b010,
x8616_sbb = 0b011,
x8616_and = 0b100,
x8616_sub = 0b101,
x8616_xor = 0b110,
x8616_cmp = 0b111,
};
typedef Enum_(U1, X8616_Group3) {
x8616_g3_test = 0b000,
x8616_g3_not = 0b010,
x8616_g3_neg = 0b011,
x8616_g3_mul = 0b100,
x8616_g3_imul = 0b101,
x8616_g3_div = 0b110,
x8616_g3_idiv = 0b111,
};
typedef Enum_(U1, X8616_IncDec) {
x8616_inc = 0b000,
x8616_dec = 0b001,
};
typedef Enum_(U1, X8616_GroupFF) {
x8616_ff_call_near = 0b010,
x8616_ff_call_far = 0b011,
x8616_ff_jmp_near = 0b100,
x8616_ff_jmp_far = 0b101,
x8616_ff_push = 0b110,
};
typedef Enum_(U1, X8616_Shift) {
x8616_rol = 0b000,
x8616_ror = 0b001,
x8616_rcl = 0b010,
x8616_rcr = 0b011,
x8616_shl = 0b100,
x8616_shr = 0b101,
x8616_sar = 0b111,
};
typedef Enum_(U1, X8616_Condition) {
x8616_cc_o = 0b0000,
x8616_cc_no = 0b0001,
x8616_cc_b = 0b0010,
x8616_cc_nb = 0b0011,
x8616_cc_e = 0b0100,
x8616_cc_ne = 0b0101,
x8616_cc_be = 0b0110,
x8616_cc_a = 0b0111,
x8616_cc_s = 0b1000,
x8616_cc_ns = 0b1001,
x8616_cc_p = 0b1010,
x8616_cc_np = 0b1011,
x8616_cc_l = 0b1100,
x8616_cc_nl = 0b1101,
x8616_cc_le = 0b1110,
x8616_cc_g = 0b1111,
};
typedef Enum_(U1, X8616_OpcodePrefix) {
x8616_opcode_mov_rm_r = 0b100010,
x8616_opcode_mov_rm_i = 0b1100011,
x8616_opcode_mov_r_i = 0b1011,
x8616_opcode_mov_acc_mem = 0b101000,
x8616_opcode_mov_seg_rm = 0b100011,
x8616_opcode_push_reg = 0b01010,
x8616_opcode_pop_reg = 0b01011,
x8616_opcode_xchg_rm_r = 0b1000011,
x8616_opcode_xchg_ax_reg = 0b10010,
x8616_opcode_in_i = 0b1110010,
x8616_opcode_in_dx = 0b1110110,
x8616_opcode_out_i = 0b1110011,
x8616_opcode_out_dx = 0b1110111,
x8616_opcode_alu_rm_i = 0b100000,
x8616_opcode_logic_rm_i = 0b1000000,
x8616_opcode_incdec_rm = 0b1111111,
x8616_opcode_inc_reg = 0b01000,
x8616_opcode_dec_reg = 0b01001,
x8616_opcode_group3 = 0b1111011,
x8616_opcode_shift_rm = 0b110100,
x8616_opcode_test_rm_r = 0b1000010,
x8616_opcode_test_acc_i = 0b1010100,
x8616_opcode_rep = 0b1111001,
x8616_opcode_movs = 0b1010010,
x8616_opcode_cmps = 0b1010011,
x8616_opcode_scas = 0b1010111,
x8616_opcode_lods = 0b1010110,
x8616_opcode_stos = 0b1010101,
x8616_opcode_jcc = 0b0111,
};
typedef Enum_(U1, X8616_Opcode) {
x8616_opcode_group_ff = 0b11111111,
x8616_opcode_pop_rm = 0b10001111,
x8616_opcode_xlat = 0b11010111,
x8616_opcode_lea = 0b10001101,
x8616_opcode_lds = 0b11000101,
x8616_opcode_les = 0b11000100,
x8616_opcode_lahf = 0b10011111,
x8616_opcode_sahf = 0b10011110,
x8616_opcode_pushf = 0b10011100,
x8616_opcode_popf = 0b10011101,
x8616_opcode_aaa = 0b00110111,
x8616_opcode_daa = 0b00100111,
x8616_opcode_aas = 0b00111111,
x8616_opcode_das = 0b00101111,
x8616_opcode_aam = 0b11010100,
x8616_opcode_aad = 0b11010101,
x8616_opcode_cbw = 0b10011000,
x8616_opcode_cwd = 0b10011001,
x8616_opcode_call_rel16 = 0b11101000,
x8616_opcode_call_far = 0b10011010,
x8616_opcode_jmp_rel16 = 0b11101001,
x8616_opcode_jmp_rel8 = 0b11101011,
x8616_opcode_jmp_far = 0b11101010,
x8616_opcode_ret = 0b11000011,
x8616_opcode_ret_i = 0b11000010,
x8616_opcode_retf = 0b11001011,
x8616_opcode_retf_i = 0b11001010,
x8616_opcode_loopnz = 0b11100000,
x8616_opcode_loopz = 0b11100001,
x8616_opcode_loop = 0b11100010,
x8616_opcode_jcxz = 0b11100011,
x8616_opcode_int = 0b11001101,
x8616_opcode_int3 = 0b11001100,
x8616_opcode_into = 0b11001110,
x8616_opcode_iret = 0b11001111,
x8616_opcode_clc = 0b11111000,
x8616_opcode_cmc = 0b11110101,
x8616_opcode_stc = 0b11111001,
x8616_opcode_cld = 0b11111100,
x8616_opcode_std = 0b11111101,
x8616_opcode_cli = 0b11111010,
x8616_opcode_sti = 0b11111011,
x8616_opcode_hlt = 0b11110100,
x8616_opcode_wait = 0b10011011,
x8616_opcode_lock = 0b11110000,
x8616_opcode_nop = 0b10010000,
};
enum {
X8616_OPCODE_MASK = 0b11111111,
X8616_OPCODE_ALU_ACC_I_FIXED = 0b10,
X8616_POST_OPCODE_AAM_AAD = 0b00001010,
// ModR/M:
// 7 6 5 4 3 2 1 0
// +-----+-------+-------+
// | mod | reg | r/m |
// +-----+-------+-------+
X8616_MODRM_RM_SHIFT = 0,
X8616_MODRM_REG_SHIFT = 3,
X8616_MODRM_MOD_SHIFT = 6,
X8616_MODRM_RM_MASK = 0b00000111,
X8616_MODRM_REG_MASK = 0b00111000,
X8616_MODRM_MOD_MASK = 0b11000000,
// Segment register occupies bits 4..3 in the segment-register MOV form.
X8616_MODRM_SR_SHIFT = 3,
X8616_MODRM_SR_MASK = 0b00011000,
X8616_MODRM_SEG_FIXED_MASK = 0b00100000,
// ... d w
X8616_OPCODE_DW_W_SHIFT = 0,
X8616_OPCODE_DW_D_SHIFT = 1,
X8616_OPCODE_DW_PREFIX_SHIFT = X8616_OPCODE_DW_D_SHIFT + 1,
X8616_OPCODE_DW_PREFIX_MASK = 0b11111100,
// ... s w
X8616_OPCODE_SW_W_SHIFT = 0,
X8616_OPCODE_SW_S_SHIFT = 1,
X8616_OPCODE_SW_PREFIX_SHIFT = X8616_OPCODE_SW_S_SHIFT + 1,
X8616_OPCODE_SW_PREFIX_MASK = 0b11111100,
// ... v w
X8616_OPCODE_VW_W_SHIFT = 0,
X8616_OPCODE_VW_V_SHIFT = 1,
X8616_OPCODE_VW_PREFIX_SHIFT = X8616_OPCODE_VW_V_SHIFT + 1,
X8616_OPCODE_VW_PREFIX_MASK = 0b11111100,
// ... z
X8616_OPCODE_Z_Z_SHIFT = 0,
X8616_OPCODE_Z_PREFIX_SHIFT = X8616_OPCODE_Z_Z_SHIFT + 1,
X8616_OPCODE_Z_PREFIX_MASK = 0b11111110,
// ... w
X8616_OPCODE_W_W_SHIFT = 0,
X8616_OPCODE_W_PREFIX_SHIFT = X8616_OPCODE_W_W_SHIFT + 1,
X8616_OPCODE_W_PREFIX_MASK = 0b11111110,
// ... reg
X8616_OPCODE_REG_REG_SHIFT = 0,
X8616_OPCODE_REG_REG_WIDTH = 3,
X8616_OPCODE_REG_REG_MASK = 0b00000111,
X8616_OPCODE_REG_PREFIX_SHIFT = X8616_OPCODE_REG_REG_SHIFT + X8616_OPCODE_REG_REG_WIDTH,
X8616_OPCODE_REG_PREFIX_MASK = 0b11111000,
// ... w reg
X8616_OPCODE_WREG_REG_SHIFT = 0,
X8616_OPCODE_WREG_REG_WIDTH = 3,
X8616_OPCODE_WREG_REG_MASK = 0b00000111,
X8616_OPCODE_WREG_W_SHIFT = X8616_OPCODE_WREG_REG_SHIFT + X8616_OPCODE_WREG_REG_WIDTH,
X8616_OPCODE_WREG_W_MASK = 0b00001000,
X8616_OPCODE_WREG_PREFIX_SHIFT = X8616_OPCODE_WREG_W_SHIFT + 1,
X8616_OPCODE_WREG_PREFIX_MASK = 0b11110000,
// ... d 0
X8616_OPCODE_D0_D_SHIFT = 1,
X8616_OPCODE_D0_PREFIX_SHIFT = X8616_OPCODE_D0_D_SHIFT + 1,
X8616_OPCODE_D0_PREFIX_MASK = 0b11111101,
// xxx sr xxx
X8616_OPCODE_SR_SHIFT = 3,
X8616_OPCODE_SR_WIDTH = 2,
X8616_OPCODE_SR_MASK = 0b00011000,
X8616_OPCODE_SR_PATTERN_MASK = 0b11100111,
X8616_OPCODE_PUSH_SR_FIXED = 0b00000110,
X8616_OPCODE_POP_SR_FIXED = 0b00000111,
X8616_OPCODE_SEG_FIXED = 0b00100110,
// 0111 cccc
X8616_OPCODE_CC_SHIFT = 0,
X8616_OPCODE_CC_WIDTH = 4,
X8616_OPCODE_CC_MASK = 0b00001111,
X8616_OPCODE_CC_PREFIX_SHIFT = X8616_OPCODE_CC_WIDTH,
// 00 op ...
X8616_OPCODE_ALU_OP_SHIFT = 3,
};
// ============================================================================
// Encoding Helpers
FI_ U1 x8616_byte_pattern_matches(U1 byte, X8616_BytePattern pattern) { return (byte & pattern.mask) == pattern.bits; }
FI_ U1 x8616_bit_field_exists (X8616_BitField field) { return field.width != 0; }
FI_ U1 x8616_bit_field_extract (U1 byte, X8616_BitField field) { return (byte >> field.shift) & u1_((1u << field.width) - 1u); }
FI_ U1 x8616_modrm_rm (U1 modrm) { return (modrm & X8616_MODRM_RM_MASK) >> X8616_MODRM_RM_SHIFT; }
FI_ U1 x8616_modrm_reg (U1 modrm) { return (modrm & X8616_MODRM_REG_MASK) >> X8616_MODRM_REG_SHIFT; }
FI_ U1 x8616_modrm_mod (U1 modrm) { return (modrm & X8616_MODRM_MOD_MASK) >> X8616_MODRM_MOD_SHIFT; }
FI_ U1 x8616_modrm_sr (U1 modrm) { return (modrm & X8616_MODRM_SR_MASK) >> X8616_MODRM_SR_SHIFT; }
// ============================================================================
// Emission DSL
// `enc_*` produces one encoded byte.
// `emit_*` expands to one or more comma-separated bytes.
//
// Intended use:
// RO_ global U1 code[] = {
// x8616_mov_r16_i(x8616_ax, 0x1234),
// x8616_mov_r16_r16(x8616_bx, x8616_ax),
// x8616_add_r16_r16(x8616_ax, x8616_bx),
// x8616_jne(-4),
// };
// ============================================================================
// Byte fields
#define x8616_enc_dw_prefix(prefix) ((prefix) << X8616_OPCODE_DW_PREFIX_SHIFT)
#define x8616_enc_sw_prefix(prefix) ((prefix) << X8616_OPCODE_SW_PREFIX_SHIFT)
#define x8616_enc_vw_prefix(prefix) ((prefix) << X8616_OPCODE_VW_PREFIX_SHIFT)
#define x8616_enc_z_prefix(prefix) ((prefix) << X8616_OPCODE_Z_PREFIX_SHIFT)
#define x8616_enc_w_prefix(prefix) ((prefix) << X8616_OPCODE_W_PREFIX_SHIFT)
#define x8616_enc_reg_prefix(prefix) ((prefix) << X8616_OPCODE_REG_PREFIX_SHIFT)
#define x8616_enc_wreg_prefix(prefix) ((prefix) << X8616_OPCODE_WREG_PREFIX_SHIFT)
#define x8616_enc_d0_prefix(prefix) ((prefix) << X8616_OPCODE_D0_PREFIX_SHIFT)
#define x8616_enc_d(d) ((d) << X8616_OPCODE_DW_D_SHIFT)
#define x8616_enc_s(s) ((s) << X8616_OPCODE_SW_S_SHIFT)
#define x8616_enc_v(v) ((v) << X8616_OPCODE_VW_V_SHIFT)
#define x8616_enc_z(z) ((z) << X8616_OPCODE_Z_Z_SHIFT)
#define x8616_enc_width(w) ((w) << X8616_OPCODE_W_W_SHIFT)
#define x8616_enc_wreg_width(w) ((w) << X8616_OPCODE_WREG_W_SHIFT)
#define x8616_enc_opcode_reg(r) ((r) << X8616_OPCODE_REG_REG_SHIFT)
#define x8616_enc_opcode_sr(sr) ((sr) << X8616_OPCODE_SR_SHIFT)
#define x8616_enc_cc(cc) ((cc) << X8616_OPCODE_CC_SHIFT)
#define x8616_enc_modrm_mod(mod) ((mod) << X8616_MODRM_MOD_SHIFT)
#define x8616_enc_modrm_reg(reg) ((reg) << X8616_MODRM_REG_SHIFT)
#define x8616_enc_modrm_rm(rm) ((rm) << X8616_MODRM_RM_SHIFT)
#define x8616_enc_modrm_sr(sr) ((sr) << X8616_MODRM_SR_SHIFT)
#define x8616_enc_dw(prefix,d,w) C_(U1, x8616_enc_dw_prefix(prefix) | x8616_enc_d(d) | x8616_enc_width(w))
#define x8616_enc_sw(prefix,s,w) C_(U1, x8616_enc_sw_prefix(prefix) | x8616_enc_s(s) | x8616_enc_width(w))
#define x8616_enc_vw(prefix,v,w) C_(U1, x8616_enc_vw_prefix(prefix) | x8616_enc_v(v) | x8616_enc_width(w))
#define x8616_enc_zp(prefix,z) C_(U1, x8616_enc_z_prefix(prefix) | x8616_enc_z(z))
#define x8616_enc_w(prefix,w) C_(U1, x8616_enc_w_prefix(prefix) | x8616_enc_width(w))
#define x8616_enc_reg(prefix,reg) C_(U1, x8616_enc_reg_prefix(prefix) | x8616_enc_opcode_reg(reg))
#define x8616_enc_wreg(prefix,w,reg) C_(U1, x8616_enc_wreg_prefix(prefix) | x8616_enc_wreg_width(w) | x8616_enc_opcode_reg(reg))
#define x8616_enc_d0(prefix,d) C_(U1, x8616_enc_d0_prefix(prefix) | x8616_enc_d(d))
#define x8616_enc_sr(fixed,sr) C_(U1, fixed | x8616_enc_opcode_sr(sr))
#define x8616_enc_jcc(cc) C_(U1, (x8616_opcode_jcc << X8616_OPCODE_CC_PREFIX_SHIFT) | x8616_enc_cc(cc))
#define x8616_enc_modrm(mod,reg,rm) C_(U1, x8616_enc_modrm_mod(mod) | x8616_enc_modrm_reg(reg) | x8616_enc_modrm_rm(rm))
#define x8616_enc_modrm_seg(mod,sr,rm) C_(U1, x8616_enc_modrm_mod(mod) | x8616_enc_modrm_sr(sr) | x8616_enc_modrm_rm(rm))
#define x8616_enc_alu_op(alu) ((alu) << X8616_OPCODE_ALU_OP_SHIFT)
#define x8616_enc_alu_acc_i_fixed (X8616_OPCODE_ALU_ACC_I_FIXED << X8616_OPCODE_W_PREFIX_SHIFT)
#define x8616_enc_alu_rm_r(alu,d,w) C_(U1, x8616_enc_alu_op(alu) | x8616_enc_d(d) | x8616_enc_width(w))
#define x8616_enc_alu_acc_i(alu,w) C_(U1, x8616_enc_alu_op(alu) | x8616_enc_alu_acc_i_fixed | x8616_enc_width(w))
// Scalar / generic packets
#define x8616_emit_u2(value) u1_(u2_(value) >> 0), u1_(u2_(value) >> 8)
#define x8616_emit_s2(value) x8616_emit_u2(value)
#define x8616_emit_op(opcode) u1_(opcode)
#define x8616_emit_op_i8(opcode,imm) u1_(opcode), u1_(imm)
#define x8616_emit_op_i16(opcode,imm) u1_(opcode), x8616_emit_u2(imm)
#define x8616_emit_op_far(opcode,seg,off) u1_(opcode), x8616_emit_u2(off), x8616_emit_u2(seg)
#define x8616_emit_modrm(opcode,mod,reg,rm) u1_(opcode), x8616_enc_modrm(mod,reg,rm)
#define x8616_emit_modrm_d8(opcode,reg,rm,disp) x8616_emit_modrm(opcode,x8616_mod_mem_d8,reg,rm), u1_(disp)
#define x8616_emit_modrm_d16(opcode,reg,rm,disp) x8616_emit_modrm(opcode,x8616_mod_mem_d16,reg,rm), x8616_emit_s2(disp)
#define x8616_emit_modrm_direct(opcode,reg,addr) x8616_emit_modrm(opcode,x8616_mod_mem,reg,x8616_ea_direct), x8616_emit_u2(addr)
#define x8616_emit_modrm_i8(opcode,mod,reg,rm,imm) x8616_emit_modrm(opcode,mod,reg,rm), u1_(imm)
#define x8616_emit_modrm_i16(opcode,mod,reg,rm,imm) x8616_emit_modrm(opcode,mod,reg,rm), x8616_emit_u2(imm)
#define x8616_emit_modrm_d8_i8(opcode,reg,rm,disp,imm) x8616_emit_modrm_d8(opcode,reg,rm,disp), u1_(imm)
#define x8616_emit_modrm_d8_i16(opcode,reg,rm,disp,imm) x8616_emit_modrm_d8(opcode,reg,rm,disp), x8616_emit_u2(imm)
#define x8616_emit_modrm_d16_i8(opcode,reg,rm,disp,imm) x8616_emit_modrm_d16(opcode,reg,rm,disp), u1_(imm)
#define x8616_emit_modrm_d16_i16(opcode,reg,rm,disp,imm) x8616_emit_modrm_d16(opcode,reg,rm,disp), x8616_emit_u2(imm)
// r/m + register / immediate packets
#define x8616_emit_rm_r(prefix,d,w,mod,reg,rm) x8616_enc_dw(prefix,d,w), x8616_enc_modrm(mod,reg,rm)
#define x8616_emit_rm_r_d8(prefix,d,w,reg,rm,disp) x8616_emit_rm_r(prefix,d,w,x8616_mod_mem_d8,reg,rm), u1_(disp)
#define x8616_emit_rm_r_d16(prefix,d,w,reg,rm,disp) x8616_emit_rm_r(prefix,d,w,x8616_mod_mem_d16,reg,rm), x8616_emit_s2(disp)
#define x8616_emit_rm_r_direct(prefix,d,w,reg,addr) x8616_emit_rm_r(prefix,d,w,x8616_mod_mem,reg,x8616_ea_direct), x8616_emit_u2(addr)
#define x8616_emit_rm_i8_w(prefix,ext,mod,rm,imm) x8616_enc_w(prefix,x8616_w_byte), x8616_enc_modrm(mod,ext,rm), u1_(imm)
#define x8616_emit_rm_i16_w(prefix,ext,mod,rm,imm) x8616_enc_w(prefix,x8616_w_word), x8616_enc_modrm(mod,ext,rm), x8616_emit_u2(imm)
#define x8616_emit_rm_i8_w_d8(prefix,ext,rm,disp,imm) x8616_enc_w(prefix,x8616_w_byte), x8616_enc_modrm(x8616_mod_mem_d8,ext,rm), u1_(disp), u1_(imm)
#define x8616_emit_rm_i16_w_d8(prefix,ext,rm,disp,imm) x8616_enc_w(prefix,x8616_w_word), x8616_enc_modrm(x8616_mod_mem_d8,ext,rm), u1_(disp), x8616_emit_u2(imm)
#define x8616_emit_rm_i8_w_d16(prefix,ext,rm,disp,imm) x8616_enc_w(prefix,x8616_w_byte), x8616_enc_modrm(x8616_mod_mem_d16,ext,rm), x8616_emit_s2(disp), u1_(imm)
#define x8616_emit_rm_i16_w_d16(prefix,ext,rm,disp,imm) x8616_enc_w(prefix,x8616_w_word), x8616_enc_modrm(x8616_mod_mem_d16,ext,rm), x8616_emit_s2(disp), x8616_emit_u2(imm)
#define x8616_emit_rm_i8(prefix,s,w,ext,mod,rm,imm) x8616_enc_sw(prefix,s,w), x8616_enc_modrm(mod,ext,rm), u1_(imm)
#define x8616_emit_rm_i16(prefix,ext,mod,rm,imm) x8616_enc_sw(prefix,x8616_s_full,x8616_w_word), x8616_enc_modrm(mod,ext,rm), x8616_emit_u2(imm)
#define x8616_emit_rm_i8_d8(prefix,s,w,ext,rm,disp,imm) x8616_enc_sw(prefix,s,w), x8616_enc_modrm(x8616_mod_mem_d8,ext,rm), u1_(disp), u1_(imm)
#define x8616_emit_rm_i16_d8(prefix,ext,rm,disp,imm) x8616_enc_sw(prefix,x8616_s_full,x8616_w_word), x8616_enc_modrm(x8616_mod_mem_d8,ext,rm), u1_(disp), x8616_emit_u2(imm)
#define x8616_emit_rm_i8_d16(prefix,s,w,ext,rm,disp,imm) x8616_enc_sw(prefix,s,w), x8616_enc_modrm(x8616_mod_mem_d16,ext,rm), x8616_emit_s2(disp), u1_(imm)
#define x8616_emit_rm_i16_d16(prefix,ext,rm,disp,imm) x8616_enc_sw(prefix,x8616_s_full,x8616_w_word), x8616_enc_modrm(x8616_mod_mem_d16,ext,rm), x8616_emit_s2(disp), x8616_emit_u2(imm)
// Segment-register packet
#define x8616_emit_seg_rm(d,mod,sr,rm) x8616_enc_d0(x8616_opcode_mov_seg_rm,d), x8616_enc_modrm_seg(mod,sr,rm)
#define x8616_emit_seg_rm_d8(d,sr,rm,disp) x8616_emit_seg_rm(d,x8616_mod_mem_d8,sr,rm), u1_(disp)
#define x8616_emit_seg_rm_d16(d,sr,rm,disp) x8616_emit_seg_rm(d,x8616_mod_mem_d16,sr,rm), x8616_emit_s2(disp)
#define x8616_emit_seg_rm_direct(d,sr,addr) x8616_emit_seg_rm(d,x8616_mod_mem,sr,x8616_ea_direct), x8616_emit_u2(addr)
// MOV
#define x8616_nop() x8616_emit_op(x8616_opcode_nop)
#define x8616_mov_r8_r8(dst,src) x8616_emit_rm_r(x8616_opcode_mov_rm_r,x8616_d_reg_dst,x8616_w_byte,x8616_mod_reg,dst,src)
#define x8616_mov_r16_r16(dst,src) x8616_emit_rm_r(x8616_opcode_mov_rm_r,x8616_d_reg_dst,x8616_w_word,x8616_mod_reg,dst,src)
#define x8616_mov_r8_i(dst,imm) x8616_enc_wreg(x8616_opcode_mov_r_i,x8616_w_byte,dst), u1_(imm)
#define x8616_mov_r16_i(dst,imm) x8616_enc_wreg(x8616_opcode_mov_r_i,x8616_w_word,dst), x8616_emit_u2(imm)
#define x8616_mov_al_moffs(addr) x8616_enc_dw(x8616_opcode_mov_acc_mem,x8616_d_acc_dst,x8616_w_byte), x8616_emit_u2(addr)
#define x8616_mov_ax_moffs(addr) x8616_enc_dw(x8616_opcode_mov_acc_mem,x8616_d_acc_dst,x8616_w_word), x8616_emit_u2(addr)
#define x8616_mov_moffs_al(addr) x8616_enc_dw(x8616_opcode_mov_acc_mem,x8616_d_mem_dst,x8616_w_byte), x8616_emit_u2(addr)
#define x8616_mov_moffs_ax(addr) x8616_enc_dw(x8616_opcode_mov_acc_mem,x8616_d_mem_dst,x8616_w_word), x8616_emit_u2(addr)
#define x8616_mov_rm_seg(mod,rm,sr) x8616_emit_seg_rm(x8616_d_rm_dst,mod,sr,rm)
#define x8616_mov_seg_rm(sr,mod,rm) x8616_emit_seg_rm(x8616_d_seg_dst,mod,sr,rm)
// Stack / exchange
#define x8616_push_r16(reg) x8616_enc_reg(x8616_opcode_push_reg,reg)
#define x8616_pop_r16(reg) x8616_enc_reg(x8616_opcode_pop_reg,reg)
#define x8616_push_seg(seg) x8616_enc_sr(X8616_OPCODE_PUSH_SR_FIXED,seg)
#define x8616_pop_seg(seg) x8616_enc_sr(X8616_OPCODE_POP_SR_FIXED,seg)
#define x8616_push_rm(mod,rm) x8616_emit_modrm(x8616_opcode_group_ff,mod,x8616_ff_push,rm)
#define x8616_pop_rm(mod,rm) x8616_emit_modrm(x8616_opcode_pop_rm,mod,0b000,rm)
#define x8616_xchg_r8_r8(a,b) x8616_enc_w(x8616_opcode_xchg_rm_r,x8616_w_byte), x8616_enc_modrm(x8616_mod_reg,a,b)
#define x8616_xchg_r16_r16(a,b) x8616_enc_w(x8616_opcode_xchg_rm_r,x8616_w_word), x8616_enc_modrm(x8616_mod_reg,a,b)
#define x8616_xchg_ax_r16(reg) x8616_enc_reg(x8616_opcode_xchg_ax_reg,reg)
// I/O / address load
#define x8616_in_al_i(port) x8616_enc_w(x8616_opcode_in_i,x8616_w_byte), u1_(port)
#define x8616_in_ax_i(port) x8616_enc_w(x8616_opcode_in_i,x8616_w_word), u1_(port)
#define x8616_in_al_dx() x8616_enc_w(x8616_opcode_in_dx,x8616_w_byte)
#define x8616_in_ax_dx() x8616_enc_w(x8616_opcode_in_dx,x8616_w_word)
#define x8616_out_i_al(port) x8616_enc_w(x8616_opcode_out_i,x8616_w_byte), u1_(port)
#define x8616_out_i_ax(port) x8616_enc_w(x8616_opcode_out_i,x8616_w_word), u1_(port)
#define x8616_out_dx_al() x8616_enc_w(x8616_opcode_out_dx,x8616_w_byte)
#define x8616_out_dx_ax() x8616_enc_w(x8616_opcode_out_dx,x8616_w_word)
#define x8616_xlat() x8616_emit_op(x8616_opcode_xlat)
#define x8616_lea(reg,mod,rm) x8616_emit_modrm(x8616_opcode_lea,mod,reg,rm)
#define x8616_lds(reg,mod,rm) x8616_emit_modrm(x8616_opcode_lds,mod,reg,rm)
#define x8616_les(reg,mod,rm) x8616_emit_modrm(x8616_opcode_les,mod,reg,rm)
#define x8616_lahf() x8616_emit_op(x8616_opcode_lahf)
#define x8616_sahf() x8616_emit_op(x8616_opcode_sahf)
#define x8616_pushf() x8616_emit_op(x8616_opcode_pushf)
#define x8616_popf() x8616_emit_op(x8616_opcode_popf)
// Arithmetic / logical
#define x8616_emit_alu_r8_r8(alu,dst,src) x8616_enc_alu_rm_r(alu,x8616_d_reg_dst,x8616_w_byte), x8616_enc_modrm(x8616_mod_reg,dst,src)
#define x8616_emit_alu_r16_r16(alu,dst,src) x8616_enc_alu_rm_r(alu,x8616_d_reg_dst,x8616_w_word), x8616_enc_modrm(x8616_mod_reg,dst,src)
#define x8616_emit_alu_r8_i(alu,dst,imm) x8616_emit_rm_i8(x8616_opcode_alu_rm_i,x8616_s_full,x8616_w_byte,alu,x8616_mod_reg,dst,imm)
#define x8616_emit_alu_r16_i(alu,dst,imm) x8616_emit_rm_i16(x8616_opcode_alu_rm_i,alu,x8616_mod_reg,dst,imm)
#define x8616_emit_alu_r16_i8s(alu,dst,imm) x8616_emit_rm_i8(x8616_opcode_alu_rm_i,x8616_s_extend,x8616_w_word,alu,x8616_mod_reg,dst,imm)
#define x8616_emit_logic_r8_i(alu,dst,imm) x8616_emit_rm_i8_w(x8616_opcode_logic_rm_i,alu,x8616_mod_reg,dst,imm)
#define x8616_emit_logic_r16_i(alu,dst,imm) x8616_emit_rm_i16_w(x8616_opcode_logic_rm_i,alu,x8616_mod_reg,dst,imm)
#define x8616_emit_alu_al_i(alu,imm) x8616_enc_alu_acc_i(alu,x8616_w_byte), u1_(imm)
#define x8616_emit_alu_ax_i(alu,imm) x8616_enc_alu_acc_i(alu,x8616_w_word), x8616_emit_u2(imm)
#define x8616_add_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_add,dst,src)
#define x8616_add_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_add,dst,src)
#define x8616_or_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_or,dst,src)
#define x8616_or_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_or,dst,src)
#define x8616_adc_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_adc,dst,src)
#define x8616_adc_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_adc,dst,src)
#define x8616_sbb_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_sbb,dst,src)
#define x8616_sbb_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_sbb,dst,src)
#define x8616_and_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_and,dst,src)
#define x8616_and_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_and,dst,src)
#define x8616_sub_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_sub,dst,src)
#define x8616_sub_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_sub,dst,src)
#define x8616_xor_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_xor,dst,src)
#define x8616_xor_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_xor,dst,src)
#define x8616_cmp_r8_r8(dst,src) x8616_emit_alu_r8_r8(x8616_cmp,dst,src)
#define x8616_cmp_r16_r16(dst,src) x8616_emit_alu_r16_r16(x8616_cmp,dst,src)
#define x8616_add_r8_i(dst,imm) x8616_emit_alu_r8_i(x8616_add,dst,imm)
#define x8616_add_r16_i(dst,imm) x8616_emit_alu_r16_i(x8616_add,dst,imm)
#define x8616_add_r16_i8s(dst,imm) x8616_emit_alu_r16_i8s(x8616_add,dst,imm)
#define x8616_or_r8_i(dst,imm) x8616_emit_logic_r8_i(x8616_or,dst,imm)
#define x8616_or_r16_i(dst,imm) x8616_emit_logic_r16_i(x8616_or,dst,imm)
#define x8616_adc_r8_i(dst,imm) x8616_emit_alu_r8_i(x8616_adc,dst,imm)
#define x8616_adc_r16_i(dst,imm) x8616_emit_alu_r16_i(x8616_adc,dst,imm)
#define x8616_adc_r16_i8s(dst,imm) x8616_emit_alu_r16_i8s(x8616_adc,dst,imm)
#define x8616_sbb_r8_i(dst,imm) x8616_emit_alu_r8_i(x8616_sbb,dst,imm)
#define x8616_sbb_r16_i(dst,imm) x8616_emit_alu_r16_i(x8616_sbb,dst,imm)
#define x8616_sbb_r16_i8s(dst,imm) x8616_emit_alu_r16_i8s(x8616_sbb,dst,imm)
#define x8616_and_r8_i(dst,imm) x8616_emit_logic_r8_i(x8616_and,dst,imm)
#define x8616_and_r16_i(dst,imm) x8616_emit_logic_r16_i(x8616_and,dst,imm)
#define x8616_sub_r8_i(dst,imm) x8616_emit_alu_r8_i(x8616_sub,dst,imm)
#define x8616_sub_r16_i(dst,imm) x8616_emit_alu_r16_i(x8616_sub,dst,imm)
#define x8616_sub_r16_i8s(dst,imm) x8616_emit_alu_r16_i8s(x8616_sub,dst,imm)
#define x8616_xor_r8_i(dst,imm) x8616_emit_logic_r8_i(x8616_xor,dst,imm)
#define x8616_xor_r16_i(dst,imm) x8616_emit_logic_r16_i(x8616_xor,dst,imm)
#define x8616_cmp_r8_i(dst,imm) x8616_emit_alu_r8_i(x8616_cmp,dst,imm)
#define x8616_cmp_r16_i(dst,imm) x8616_emit_alu_r16_i(x8616_cmp,dst,imm)
#define x8616_cmp_r16_i8s(dst,imm) x8616_emit_alu_r16_i8s(x8616_cmp,dst,imm)
// INC / DEC / unary
#define x8616_inc_r16(reg) x8616_enc_reg(x8616_opcode_inc_reg,reg)
#define x8616_dec_r16(reg) x8616_enc_reg(x8616_opcode_dec_reg,reg)
#define x8616_inc_rm(w,mod,rm) x8616_emit_modrm(x8616_enc_w(x8616_opcode_incdec_rm,w),mod,x8616_inc,rm)
#define x8616_dec_rm(w,mod,rm) x8616_emit_modrm(x8616_enc_w(x8616_opcode_incdec_rm,w),mod,x8616_dec,rm)
#define x8616_unary_rm(ext,w,mod,rm) x8616_emit_modrm(x8616_enc_w(x8616_opcode_group3,w),mod,ext,rm)
#define x8616_not_rm(w,mod,rm) x8616_unary_rm(x8616_g3_not,w,mod,rm)
#define x8616_neg_rm(w,mod,rm) x8616_unary_rm(x8616_g3_neg,w,mod,rm)
#define x8616_mul_rm(w,mod,rm) x8616_unary_rm(x8616_g3_mul,w,mod,rm)
#define x8616_imul_rm(w,mod,rm) x8616_unary_rm(x8616_g3_imul,w,mod,rm)
#define x8616_div_rm(w,mod,rm) x8616_unary_rm(x8616_g3_div,w,mod,rm)
#define x8616_idiv_rm(w,mod,rm) x8616_unary_rm(x8616_g3_idiv,w,mod,rm)
#define x8616_aaa() x8616_emit_op(x8616_opcode_aaa)
#define x8616_daa() x8616_emit_op(x8616_opcode_daa)
#define x8616_aas() x8616_emit_op(x8616_opcode_aas)
#define x8616_das() x8616_emit_op(x8616_opcode_das)
#define x8616_aam() x8616_emit_op_i8(x8616_opcode_aam,X8616_POST_OPCODE_AAM_AAD)
#define x8616_aad() x8616_emit_op_i8(x8616_opcode_aad,X8616_POST_OPCODE_AAM_AAD)
#define x8616_cbw() x8616_emit_op(x8616_opcode_cbw)
#define x8616_cwd() x8616_emit_op(x8616_opcode_cwd)
// Shift / rotate / TEST
#define x8616_shift_rm(shift,v,w,mod,rm) x8616_emit_modrm(x8616_enc_vw(x8616_opcode_shift_rm,v,w),mod,shift,rm)
#define x8616_shl_r8_1(reg) x8616_shift_rm(x8616_shl,x8616_v_one,x8616_w_byte,x8616_mod_reg,reg)
#define x8616_shl_r16_1(reg) x8616_shift_rm(x8616_shl,x8616_v_one,x8616_w_word,x8616_mod_reg,reg)
#define x8616_shl_r8_cl(reg) x8616_shift_rm(x8616_shl,x8616_v_cl,x8616_w_byte,x8616_mod_reg,reg)
#define x8616_shl_r16_cl(reg) x8616_shift_rm(x8616_shl,x8616_v_cl,x8616_w_word,x8616_mod_reg,reg)
#define x8616_test_r8_r8(a,b) x8616_enc_w(x8616_opcode_test_rm_r,x8616_w_byte), x8616_enc_modrm(x8616_mod_reg,b,a)
#define x8616_test_r16_r16(a,b) x8616_enc_w(x8616_opcode_test_rm_r,x8616_w_word), x8616_enc_modrm(x8616_mod_reg,b,a)
#define x8616_test_r8_i(reg,imm) x8616_emit_modrm_i8(x8616_enc_w(x8616_opcode_group3,x8616_w_byte),x8616_mod_reg,x8616_g3_test,reg,imm)
#define x8616_test_r16_i(reg,imm) x8616_emit_modrm_i16(x8616_enc_w(x8616_opcode_group3,x8616_w_word),x8616_mod_reg,x8616_g3_test,reg,imm)
#define x8616_test_al_i(imm) x8616_enc_w(x8616_opcode_test_acc_i,x8616_w_byte), u1_(imm)
#define x8616_test_ax_i(imm) x8616_enc_w(x8616_opcode_test_acc_i,x8616_w_word), x8616_emit_u2(imm)
// String / prefixes
#define x8616_rep_prefix() x8616_enc_zp(x8616_opcode_rep,x8616_rep)
#define x8616_repne_prefix() x8616_enc_zp(x8616_opcode_rep,x8616_repne)
#define x8616_movsb() x8616_enc_w(x8616_opcode_movs,x8616_w_byte)
#define x8616_movsw() x8616_enc_w(x8616_opcode_movs,x8616_w_word)
#define x8616_cmpsb() x8616_enc_w(x8616_opcode_cmps,x8616_w_byte)
#define x8616_cmpsw() x8616_enc_w(x8616_opcode_cmps,x8616_w_word)
#define x8616_scasb() x8616_enc_w(x8616_opcode_scas,x8616_w_byte)
#define x8616_scasw() x8616_enc_w(x8616_opcode_scas,x8616_w_word)
#define x8616_lodsb() x8616_enc_w(x8616_opcode_lods,x8616_w_byte)
#define x8616_lodsw() x8616_enc_w(x8616_opcode_lods,x8616_w_word)
#define x8616_stosb() x8616_enc_w(x8616_opcode_stos,x8616_w_byte)
#define x8616_stosw() x8616_enc_w(x8616_opcode_stos,x8616_w_word)
#define x8616_lock_prefix() x8616_emit_op(x8616_opcode_lock)
#define x8616_segment_prefix(seg) x8616_enc_sr(X8616_OPCODE_SEG_FIXED,seg)
// Control transfer
#define x8616_call_rel16(rel) x8616_emit_op_i16(x8616_opcode_call_rel16,rel)
#define x8616_call_far(seg,off) x8616_emit_op_far(x8616_opcode_call_far,seg,off)
#define x8616_call_rm(mod,rm) x8616_emit_modrm(x8616_opcode_group_ff,mod,x8616_ff_call_near,rm)
#define x8616_call_far_rm(mod,rm) x8616_emit_modrm(x8616_opcode_group_ff,mod,x8616_ff_call_far,rm)
#define x8616_jmp_rel16(rel) x8616_emit_op_i16(x8616_opcode_jmp_rel16,rel)
#define x8616_jmp_rel8(rel) x8616_emit_op_i8(x8616_opcode_jmp_rel8,rel)
#define x8616_jmp_far(seg,off) x8616_emit_op_far(x8616_opcode_jmp_far,seg,off)
#define x8616_jmp_rm(mod,rm) x8616_emit_modrm(x8616_opcode_group_ff,mod,x8616_ff_jmp_near,rm)
#define x8616_jmp_far_rm(mod,rm) x8616_emit_modrm(x8616_opcode_group_ff,mod,x8616_ff_jmp_far,rm)
#define x8616_ret() x8616_emit_op(x8616_opcode_ret)
#define x8616_ret_i(bytes) x8616_emit_op_i16(x8616_opcode_ret_i,bytes)
#define x8616_retf() x8616_emit_op(x8616_opcode_retf)
#define x8616_retf_i(bytes) x8616_emit_op_i16(x8616_opcode_retf_i,bytes)
#define x8616_jcc(cc,rel) x8616_enc_jcc(cc), u1_(rel)
#define x8616_jo(rel) x8616_jcc(x8616_cc_o,rel)
#define x8616_jno(rel) x8616_jcc(x8616_cc_no,rel)
#define x8616_jb(rel) x8616_jcc(x8616_cc_b,rel)
#define x8616_jnb(rel) x8616_jcc(x8616_cc_nb,rel)
#define x8616_je(rel) x8616_jcc(x8616_cc_e,rel)
#define x8616_jne(rel) x8616_jcc(x8616_cc_ne,rel)
#define x8616_jbe(rel) x8616_jcc(x8616_cc_be,rel)
#define x8616_ja(rel) x8616_jcc(x8616_cc_a,rel)
#define x8616_js(rel) x8616_jcc(x8616_cc_s,rel)
#define x8616_jns(rel) x8616_jcc(x8616_cc_ns,rel)
#define x8616_jp(rel) x8616_jcc(x8616_cc_p,rel)
#define x8616_jnp(rel) x8616_jcc(x8616_cc_np,rel)
#define x8616_jl(rel) x8616_jcc(x8616_cc_l,rel)
#define x8616_jnl(rel) x8616_jcc(x8616_cc_nl,rel)
#define x8616_jle(rel) x8616_jcc(x8616_cc_le,rel)
#define x8616_jg(rel) x8616_jcc(x8616_cc_g,rel)
#define x8616_loopnz(rel) x8616_emit_op_i8(x8616_opcode_loopnz,rel)
#define x8616_loopz(rel) x8616_emit_op_i8(x8616_opcode_loopz,rel)
#define x8616_loop(rel) x8616_emit_op_i8(x8616_opcode_loop,rel)
#define x8616_jcxz(rel) x8616_emit_op_i8(x8616_opcode_jcxz,rel)
// Interrupt / flags / machine control
#define x8616_int(vector) x8616_emit_op_i8(x8616_opcode_int,vector)
#define x8616_int3() x8616_emit_op(x8616_opcode_int3)
#define x8616_into() x8616_emit_op(x8616_opcode_into)
#define x8616_iret() x8616_emit_op(x8616_opcode_iret)
#define x8616_clc() x8616_emit_op(x8616_opcode_clc)
#define x8616_cmc() x8616_emit_op(x8616_opcode_cmc)
#define x8616_stc() x8616_emit_op(x8616_opcode_stc)
#define x8616_cld() x8616_emit_op(x8616_opcode_cld)
#define x8616_std() x8616_emit_op(x8616_opcode_std)
#define x8616_cli() x8616_emit_op(x8616_opcode_cli)
#define x8616_sti() x8616_emit_op(x8616_opcode_sti)
#define x8616_hlt() x8616_emit_op(x8616_opcode_hlt)
#define x8616_wait() x8616_emit_op(x8616_opcode_wait)
File diff suppressed because it is too large Load Diff
+359
View File
@@ -0,0 +1,359 @@
// Generated from encoder_table.h. Do not hand-edit.
// Plan 0 is the all-zero nil/invalid plan.
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}, },
{ 0x020d, 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}, },
{ 0x0088, 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}, },
{ 0x0205, 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}, },
{ 0x0080, 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}, },
{ 0x0201, 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, {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}, },
{ 0x0080, 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}, },
{ 0x0008, 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}, },
{ 0x0008, 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}, },
{ 0x0201, 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}, },
{ 0x0201, 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, 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, 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}, },
{ 0x0219, 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}, },
{ 0x020d, 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}, },
{ 0x0008, 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}, },
{ 0x0219, 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}, },
{ 0x020d, 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}, },
{ 0x0008, 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}, },
{ 0x0209, 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}, },
{ 0x020d, 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}, },
{ 0x0008, 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}, },
{ 0x0209, 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}, },
{ 0x020d, 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}, },
{ 0x0008, 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}, },
{ 0x0080, 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, 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}, },
{ 0x0080, 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}, },
{ 0x0209, 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}, },
{ 0x0209, 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}, },
{ 0x0209, 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, 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}, },
{ 0x0002, 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, 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}, },
{ 0x0229, 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}, },
{ 0x0229, 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}, },
{ 0x0229, 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}, },
{ 0x0209, 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}, },
{ 0x0008, 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}, },
{ 0x0008, 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}, },
{ 0x0008, 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}, },
{ 0x0008, 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}, },
{ 0x0500, 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}, },
{ 0x0201, 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}, },
{ 0x0201, 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, {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}, },
{ 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}, },
{ 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, 0x39, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x39, 0x00, 0x00, {0x09, 0x00}, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x40, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x48, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3d, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x45, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3a, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x42, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3e, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x46, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x41, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x49, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3f, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x47, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3b, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x43, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x3c, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x44, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4c, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4b, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4a, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4d, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4e, 0x00, 0x00, {0x08, 0x00}, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x4f, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x50, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x51, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x52, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x53, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x54, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x55, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x56, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x57, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x58, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x59, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
{ 0x0000, 0x5a, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
};
RO_ global U2 x8616_decode_dispatch[256] =
{
0x001a, 0x001a, 0x001a, 0x001a, 0x001c, 0x001c, 0x0008, 0x000b, 0x001d, 0x001d, 0x001d, 0x001d, 0x001f, 0x001f, 0x0008, 0x000b,
0x0020, 0x0020, 0x0020, 0x0020, 0x0022, 0x0022, 0x0008, 0x000b, 0x0023, 0x0023, 0x0023, 0x0023, 0x0025, 0x0025, 0x0008, 0x000b,
0x0026, 0x0026, 0x0026, 0x0026, 0x0028, 0x0028, 0x0055, 0x0035, 0x0029, 0x0029, 0x0029, 0x0029, 0x002b, 0x002b, 0x0055, 0x003f,
0x002c, 0x002c, 0x002c, 0x002c, 0x002e, 0x002e, 0x0055, 0x0034, 0x002f, 0x002f, 0x002f, 0x002f, 0x0031, 0x0031, 0x0055, 0x003e,
0x0033, 0x0033, 0x0033, 0x0033, 0x0033, 0x0033, 0x0033, 0x0033, 0x0037, 0x0037, 0x0037, 0x0037, 0x0037, 0x0037, 0x0037, 0x0037,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072,
0x8000, 0x8100, 0x8200, 0x8300, 0x004b, 0x004b, 0x000c, 0x000c, 0x0001, 0x0001, 0x0001, 0x0001, 0x0005, 0x0013, 0x0005, 0x0009,
0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x0042, 0x0043, 0x0058, 0x0083, 0x0018, 0x0019, 0x0017, 0x0016,
0x0004, 0x0004, 0x0004, 0x0004, 0x004f, 0x004f, 0x0050, 0x0050, 0x004d, 0x004d, 0x0053, 0x0053, 0x0052, 0x0052, 0x0051, 0x0051,
0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
0x0000, 0x0000, 0x0060, 0x005f, 0x0015, 0x0014, 0x0002, 0x0002, 0x0000, 0x0000, 0x0062, 0x0061, 0x0078, 0x0077, 0x0079, 0x007a,
0x8400, 0x8500, 0x8600, 0x8700, 0x0040, 0x0041, 0x0000, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0073, 0x0074, 0x0075, 0x0076, 0x000e, 0x000e, 0x0010, 0x0010, 0x0056, 0x005a, 0x005d, 0x005b, 0x000f, 0x000f, 0x0011, 0x0011,
0x0054, 0x0000, 0x004e, 0x004e, 0x0082, 0x007c, 0x8800, 0x8900, 0x007b, 0x007d, 0x0080, 0x0081, 0x007e, 0x007f, 0x8a00, 0x8b00,
};
RO_ global U1 x8616_decode_aux[3072] =
{
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
enum {
X8616_DECODE_PLAN_COUNT = 132,
X8616_DECODE_AUX_COUNT = 3072,
};
+100
View File
@@ -0,0 +1,100 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "duffle/dsl.h"
# include "duffle/memory.h"
# include "duffle/text.h"
#endif
typedef Enum_(U1, X8616_InfoKind) {
x8616_info_note = 0x0,
x8616_info_warning = 0x1,
x8616_info_error = 0x2,
};
typedef Enum_(U1, X8616_InfoCode) {
x8616_info_none = 0x00,
x8616_info_invalid_opcode = 0x01,
x8616_info_invalid_opcode_extension = 0x02,
x8616_info_invalid_post_opcode = 0x03,
x8616_info_truncated_instruction = 0x04,
x8616_info_output_full = 0x05,
x8616_info_gen_multiple_payloads = 0x06,
x8616_info_gen_body_cap_exceeded = 0x07,
x8616_info_gen_aux_cap_exceeded = 0x08,
x8616_info_gen_ambiguous_decode = 0x09,
x8616_info_gen_dispatch_mismatch = 0x0A,
x8616_info_count,
};
/* The hot path stores structured diagnostic facts only.
Human-readable text is a projection of those facts. */
typedef Struct_(X8616_InfoMsg) {
X8616_InfoMsg* next;
X8616_InfoKind kind;
X8616_InfoCode code;
U4 source_offset;
U2 source_size;
U4 expected;
U4 actual;
Str8 text;
};
/* Static templates use the same <identifier> vocabulary as Duffle's str8_fmt_ktl_buf path.
The decoder itself never expands these. */
RO_ global Str8 x8616_info_templates[x8616_info_count] = {
[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_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_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_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_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_dispatch_mismatch] = slit8("Generated dispatch mismatch for opcode/second-byte key <offset>: expected <expected>, actual <actual>."),
};
typedef Struct_(X8616_InfoList) {
X8616_InfoMsg* first;
X8616_InfoMsg* last;
U4 count;
U4 error_count;
U4 warning_count;
U4 dropped_count;
};
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
, X8616_InfoList_R list
, X8616_InfoKind kind
, X8616_InfoCode code
, U4 source_offset
, U2 source_size
, U4 expected
, U4 actual
){
assert(scratch != nullptr);
list->count += 1;
list->error_count += kind == x8616_info_error;
list->warning_count += kind == x8616_info_warning;
U4 allocation_size = align_pow2(S_(X8616_InfoMsg), MEM_ALIGNMENT_DEFAULT);
U4 left = scratch->capacity - scratch->used;
if (allocation_size > left) { ++ list->dropped_count; return; }
X8616_InfoMsg_R msg = farena_push_type(scratch, X8616_InfoMsg);
// msg[0] = (X8616_InfoMsg){0};
msg->kind = kind;
msg->code = code;
msg->source_offset = source_offset;
msg->source_size = source_size;
msg->expected = expected;
msg->actual = actual;
msg->text = x8616_info_template(code);
sll_queue_push_n(list->first, list->last, msg, next);
}
+22
View File
@@ -0,0 +1,22 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "duffle/tables.h"
# include "duffle/text.h"
# include "info.h"
#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; };
FI_ Str8
x8616_info_render(Slice output, X8616_InfoMsg_R msg, X8616_InfoTextValues values) {
KTL_Slot_Str8 slots[] = {
{ ktl_str8_key("offset"), values.offset },
{ ktl_str8_key("expected"), values.expected },
{ ktl_str8_key("actual"), values.actual },
};
return str8_fmt_ktl_buf(output, ktl_str8_from_arr(slots), msg->text);
}
+18
View File
@@ -0,0 +1,18 @@
# C Duffle Library
```txt
ISA: amd64
Sandbox: Windows 11 (for now)
Compiler: clang
Standard: c11
```
Scrapped togther stuff from several repos and studies.
Some of my favorite C code:
```txt
stb
gb or zpl
raddebugger
```
+21
View File
@@ -0,0 +1,21 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# if _WIN32
# include "win32.h"
# endif
#endif
#pragma region Debug
#define debug_trap() __builtin_debugtrap()
#if BUILD_DEBUG
FI_ void assert(U8 cond);
#else
#define assert(cond)
#endif
#define trap() __builtin_trap()
#define assert_always(x) do { if((x) == false) {trap();} } while(0)
#pragma endregion Debug
+127
View File
@@ -0,0 +1,127 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
#endif
#define asm_out /* outputs */
#define asm_in /* inputs */
#define asm_clobber /* clobbers */
#define asm_out_r(name) [name] "=r"(name)
#define asm_in_r(name) [name] "r"(name)
#define asm_out_x(name) [name] "=&x"(name) /* XMM, earlyclobber */
#define asm_out_x0(name) [name] "=x"(name) /* XMM, no earlyclobber */
#define asm_in_x(name) [name] "x"(name)
#define x64_r(name) "%[" #name "]"
#define x64_m(name) "(%[" #name "])"
#define x64_xmm(name) "%x[" #name "]"
typedef U8 U8x2 attribute(vector_size(16));
typedef U8 U8x4 attribute(vector_size(32));
typedef U1 U1x16 attribute(vector_size(16));
#define x64_u4_from_byte_hits(dst, src) "pmovmskb " x64_r(src) ", " x64_r(dst) "\n"
#define x64_u4_count_trailing_zeros(dst, src) "tzcntl " x64_r(src) ", " x64_r(dst) "\n"
#define x64_u1x16_repeat_dwords(dst, src, n) "pshufd $" #n ", " x64_r(src) ", " x64_r(dst) "\n"
#define x64_u1x16_load_mem4(dst, src) "movd " x64_r(src) ", " x64_r(dst) "\n"
#define x64_u1x16_load_mem8(dst, src) "movq " x64_m(src) ", " x64_r(dst) "\n"
#define x64_u1x16_load_mem16(dst, src) "movdqu " x64_m(src) ", " x64_r(dst) "\n"
#define x64_u1x16_match_bytes(dst, src) "pcmpeqb " x64_r(src) ", " x64_r(dst) "\n"
#define x64_u8x2_load_u8(dst, src) "vmovq " x64_m(src) ", " x64_r(dst) "\n"
#define x64_u8x2_insert_u8(dst, src, n) "vpinsrq $" #n ", " x64_m(src) ", " x64_r(dst) ", " x64_r(dst) "\n"
#define x64_u8x4_insert_xmm(dst, src, n) "vinserti128 $" #n ", " x64_r(src) ", " x64_r(dst) ", " x64_r(dst) "\n"
#define x64_u8x4_broadcast(dst, src) "vpbroadcastq " x64_r(src) ", " 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"
I_ U4 count_trailing_zeros_u4(U4 mask) {
U4 n;
asm volatile(
x64_u4_count_trailing_zeros(n, mask)
asm_out : asm_out_r(n)
asm_in : asm_in_r(mask)
);
return n;
}
I_ U1x16 splat_u4_u1x16(U4 b4) {
U1x16 v;
asm volatile(
x64_u1x16_load_mem4 (v, b4)
x64_u1x16_repeat_dwords(v, v, 0)
asm_out : asm_out_x0(v)
asm_in : asm_in_r(b4)
);
return v;
}
I_ U4 mask_eq8_u1x16(U1_R p, U1x16 needle) {
U1x16 chunk;
U4 mask;
asm volatile(
x64_u1x16_load_mem8 (chunk, p)
x64_u1x16_match_bytes(chunk, needle)
x64_u4_from_byte_hits(mask, chunk)
asm_out : asm_out_x(chunk), asm_out_r(mask)
asm_in : asm_in_r(p), asm_in_x(needle)
asm_clobber : "memory"
);
return mask; /* movq zero-fills the high 8 bytes; bits 815 stay 0 */
}
I_ U4 mask_eq16_u1x16(U1_R p, U1x16 needle) {
U1x16 chunk;
U4 mask;
asm volatile(
x64_u1x16_load_mem16 (chunk, p)
x64_u1x16_match_bytes(chunk, needle)
x64_u4_from_byte_hits(mask, chunk)
asm_out : asm_out_x(chunk), asm_out_r(mask)
asm_in : asm_in_r(p), asm_in_x(needle)
asm_clobber : "memory"
);
return mask;
}
I_ U8 find_u1_via_u1x16(U1_R p, U8 len, U1 ch, U1x16 needle) {
U8 i = 0;
while (len - i >= 16) {
U4 mask = mask_eq16_u1x16(p + i, needle);
if (mask) return i + C_(U8, count_trailing_zeros_u4(mask));
i += 16;
}
while (len - i >= 8) {
U4 mask = mask_eq8_u1x16(p + i, needle);
if (mask) return i + C_(U8, count_trailing_zeros_u4(mask));
i += 8;
}
while (i < len) {
if (p[i] == ch) return i;
++ i;
}
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) {
U8x2 lo, hi;
U8x4 keys, splat, eq;
U4 mask;
asm volatile(
x64_u8x2_load_u8 (lo, p0)
x64_u8x2_insert_u8(lo, p1, 1)
x64_u8x2_load_u8 (hi, p2)
x64_u8x2_insert_u8(hi, p3, 1)
x64_u8x4_insert_xmm(keys, lo, 0)
x64_u8x4_insert_xmm(keys, hi, 1)
x64_u8x4_broadcast(splat, key)
x64_u8x4_match(eq, keys, splat)
x64_u4_from_qword_hits(mask, eq)
asm_out : asm_out_x(lo), asm_out_x(hi), asm_out_x(keys), asm_out_x(splat), asm_out_x(eq), asm_out_r(mask)
asm_in : asm_in_r(p0), asm_in_r(p1), asm_in_r(p2), asm_in_r(p3), asm_in_r(key)
asm_clobber : "memory"
);
return mask;
}
+309
View File
@@ -0,0 +1,309 @@
/*
C DSL Duffle
ISA: amd64
Sandbox: Windows 11
Compiler: clang
Standard: c23
*/
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wuninitialized"
#pragma clang diagnostic ignored "-Wmicrosoft-enum-forward-reference"
// #pragma comment(lib, "Advapi32.lib")
// #pragma comment(lib, "gdi32.lib")
// #pragma comment(lib, "Kernel32.lib")
// #pragma comment(lib, "msvcrt.lib")
// #pragma comment(lib, "user32.lib")
// #pragma comment(lib, "ucrt.lib")
// #pragma comment(lib, "vcruntime.lib")
#pragma region Platform
#define CLANG_OPTIMIZE_DISABLE _Pragma("clang optimize off")
#define CLANG_OPTIMIZE_ENABLE _Pragma("clang optimize on")
#define DUFFLE_x86_64 1
#define DUFFLE_WINDOWS 1
#define WinAPI __attribute((__stdcall__)) __attribute__((__force_align_arg_pointer__)) // Win32 Syscall FFI
#define os_layer // Marker for interface resolved by os platform layer.
#pragma endregion Platform
#define offset_of(type, member) cast(U8,__builtin_offsetof(type,member))
#define static_assert _Static_assert
#define typeof __typeof__
#define typeof_ptr(ptr) typeof((ptr)[0])
#define typeof_same(a, b) _Generic((a), typeof((b)): 1, default: 0)
#define m_expand(...) __VA_ARGS__
#define glue_impl(A, B) A ## B
#define glue(A, B) glue_impl(A, B)
#define tmpl(prefix, type) prefix ## _ ## type
#define stringify_impl(...) #__VA_ARGS__
#define stringify(...) stringify_impl(__VA_ARGS__)
#define VA_Sel_1( _1, ... ) _1 // <-- Of all th args passed pick _1.
#define VA_Sel_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2.
#define VA_Sel_3( _1, _2, _3, ... ) _3 // etc..
#define global static // Mark global data
#define gknown // Mark global data used in procedure
#define LP_ static // static data within procedure scope
#define internal static // internal
#define attribute(directive) __attribute__((directive))
#define asm __asm__
#define align_(value) attribute(aligned(value)) // for easy alignment
#define C_(type,data) ((type)(data)) // for enforced precedence
#define expect_(x, y) __builtin_expect(x, y) // so compiler knows the common path
#define cexpr_ __builtin_constant_p
#define I_ internal inline
#define FI_ inline attribute(always_inline) // inline always
#define NI_ internal attribute(noinline) // inline never
#define RO_ attribute(section(".rodata")) // Read only data allocation
#define T_ typeof //
#define T_same(a,b) _Generic((a), typeof((b)): 1, default: 0)
#define R_ restrict
#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 v_(ptr) C_(T_(ptr[0])V_*, ptr) //
#define tr_(type, ptr) C_(type *R_, ptr)
#define tv_(type, ptr) C_(type V_*, ptr)
#define TypeR_(type) type *R_ type ## _R // type *restrict type_R
#define TypeV_(type) type V_* type ## _V // type volatile* type_V
#define PtrSet_(type) TypeR_(type); typedef TypeV_(type)
#define TSet_(type) type; typedef PtrSet_(type)
#define Array_len(a) (U4)(sizeof(a) / sizeof(typeof((a)[0])))
#define Array_decl(type, ...) (type[]){__VA_ARGS__}
#define Array_sym(type,len) A ## len ## _ ## type
#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 Bit_(id,b) id = (1 << b), tmpl(id,pos) = b
#define Enum_(underlying_type, symbol) underlying_type TSet_(symbol); enum symbol
#define Proc_(symbol) symbol
#define Relative_(symbol) // Does nothing but annotate that a symbol is associated with another.
#define Struct_(symbol) struct symbol TSet_(symbol); struct symbol
#define Union_(symbol) union symbol TSet_(symbol); union symbol
#define Opt_(proc) Struct_(tmpl(Opt,proc))
#define opt_(symbol, ...) (tmpl(Opt,symbol)){__VA_ARGS__}
#define Ret_(proc) Struct_(tmpl(Ret,proc))
#define ret_(proc) tmpl(Ret,proc) proc
// Using Byte-Width convention for the fundamental types.
typedef __UINT8_TYPE__ TSet_(U1);
typedef __UINT16_TYPE__ TSet_(U2);
typedef __UINT32_TYPE__ TSet_(U4);
typedef __UINT64_TYPE__ TSet_(U8);
typedef __INT8_TYPE__ TSet_(S1);
typedef __INT16_TYPE__ TSet_(S2);
typedef __INT32_TYPE__ TSet_(S4);
typedef __INT64_TYPE__ TSet_(S8);
typedef unsigned char TSet_(B1);
typedef __UINT16_TYPE__ TSet_(B2);
typedef __UINT32_TYPE__ TSet_(B4);
typedef __UINT64_TYPE__ TSet_(B8);
typedef float F4_2 __attribute__((vector_size(16)));
#define u1_(value) C_(U1, value)
#define u2_(value) C_(U2, value)
#define u4_(value) C_(U4, value)
#define u8_(value) C_(U8, value)
#define s1_(value) C_(S1, value)
#define s2_(value) C_(S2, value)
#define s4_(value) C_(S4, value)
#define s8_(value) C_(S8, value)
#define u1_r(value) C_(U1 *R_, value)
#define u2_r(value) C_(U2 *R_, value)
#define u4_r(value) C_(U4 *R_, value)
#define u8_r(value) C_(U8 *R_, value)
#define u1_v(value) C_(U1 V_*, value)
#define u2_v(value) C_(U2 V_*, value)
#define u4_v(value) C_(U4 V_*, value)
#define u8_v(value) C_(U8 V_*, value)
enum { false = 0, true = 1, true_overflow, };
#define u4_lo(value) ((value) & 0xFFFFU)
#define u4_hi(value) ((value) >> 12)
typedef void Proc_(VoidFn) (void);
#define kilo(n) (n << 10)
#define mega(n) (n << 20)
#define giga(n) (n << 30)
#define tera(n) (n << 40)
#define null C_(U8, 0)
#define nullptr C_(void*, 0)
#define O_(type, field) C_(U8, & C_(type*,0)->field)
#define OA_(type, member, idx) C_(U8, & C_(type*,0)->member[idx])
#define OT_(field) O_(typeof_ptr(& field), filed))
#define S_(data) C_(U8, sizeof(data))
#define sop_1(op,a,b) C_(U1, s1_(a) op s1_(b))
#define sop_2(op,a,b) C_(U2, s2_(a) op s2_(b))
#define sop_4(op,a,b) C_(U4, s4_(a) op s4_(b))
#define sop_8(op,a,b) C_(U8, s8_(a) op s8_(b))
#undef def_signed_op
#define def_signed_op(id,op,width) FI_ U ## width id ## _s ## width(U ## width a, U ## width b) {return sop_ ## width(op, a, b); }
#define def_signed_ops(id,op) def_signed_op(id, op, 1) def_signed_op(id, op, 2) def_signed_op(id, op, 4) def_signed_op(id, op, 8)
def_signed_ops(add, +)
def_signed_ops(sub, -)
def_signed_ops(mut, *)
def_signed_ops(div, /)
def_signed_ops(gt, >)
def_signed_ops(lt, <)
def_signed_ops(ge, >=)
def_signed_ops(le, <=)
#undef def_signed_ops
#undef def_signed_op
#define def_generic_sop(op, a, ...) _Generic((a), U1: op ## _s1, U2: op ## _s2, U4: op ## _s4, U8: op ## _s8) (a, __VA_ARGS__)
#define add_s(a,b) def_generic_sop(add,a,b)
#define sub_s(a,b) def_generic_sop(sub,a,b)
#define mut_s(a,b) def_generic_sop(mut,a,b)
#define gt_s(a,b) def_generic_sop(gt, a,b)
#define lt_s(a,b) def_generic_sop(lt, a,b)
#define ge_s(a,b) def_generic_sop(ge, a,b)
#define le_s(a,b) def_generic_sop(le, a,b)
#undef def_generic_sop
#define alignas _Alignas
#define alignof _Alignof
#define byte_pad(amount, ...) B1 glue(_PAD_, __VA_ARGS__) [amount]
#define pcast(type, data) (C_(type*, & (data)) [0])
#define dbg_args(...) __VA_ARGS__
#pragma region Control Flow & Iteration
#define unreachable() __builtin_unreachable()
#define each_iter(type, iter, end) (type iter = 0; iter < end; ++ iter)
#define index_iter(type, iter, begin, op, end) (type iter = begin; iter op end; (begin < end ? ++ iter : -- iter))
#define range_iter(iter,op,range) (T_((range).p0) iter = (range).p0; iter op (range).p1; ((range).p0 < (range).p1 ? ++ iter : -- iter))
#define defer(expr) for(U4 once= 1; once!=1;++ once,(expr)) // Basic do something after body
#define defer_rewind(cursor) for(T_(cursor) sp=cursor,once=0; once!=1;++ once,cursor=sp) // Used with arenas/stacks
#define defer_info(type,expr, ...) for(type info={__VA_ARGS__}; info.once!=1;++info.once,(expr)) // Defer with tracked state
#define scope(begin,end) for(U4 once=(1,(begin)); once!=1;++ once,(end )) // Do things before or after a scope
#define scope_info(type,begin,end) for(type info=begin; info.once!=1;++info.once,(end ))
#define do_while(cond) for (U4 once=0; once!=1 || (cond); ++once)
#define span_iter(type, iter, m_begin, op, m_end) ( \
tmpl(Iter_Span,type) iter = { \
.r = {(m_begin), (m_end)}, \
.cursor = (m_begin) }; \
iter.cursor op iter.r.end; \
++ iter.cursor \
)
#define Span_(type) \
Struct_(tmpl( Span,type)) { type begin; type end; }; \
typedef Struct_(tmpl(Iter_Span,type)) { tmpl(Span,type) r; type cursor; }
#pragma endregion Control Flow & Iteration
typedef Span_(S4);
typedef Span_(U4);
typedef Span_(U8);
#pragma region Thread Coherence
FI_ void barrier_compiler(void){asm volatile("::""memory");} // Compiler Barrier
FI_ void barrier_memory (void){__builtin_ia32_mfence();} // Memory Barrier
FI_ void barrier_read (void){__builtin_ia32_lfence();} // Read Barrier
FI_ void barrier_write (void){__builtin_ia32_sfence();} // Write Barrier
// x86-64
FI_ U4 atm_add_u4 (U4_R addr, U4 value){asm volatile("lock xaddl %0,%1":"=r"(value),"=m"(addr[0]):"0"(value),"m"(addr[0]):"memory","cc");return value;}
FI_ U8 atm_add_u8 (U8_R addr, U8 value){asm volatile("lock xaddq %0,%1":"=r"(value),"=m"(addr[0]):"0"(value),"m"(addr[0]):"memory","cc");return value;}
FI_ U4 atm_swap_u4(U4_R addr, U4 value){asm volatile("lock xchgl %0,%1":"=r"(value),"=m"(addr[0]):"0"(value),"m"(addr[0]):"memory","cc");return value;}
FI_ U8 atm_swap_u8(U8_R addr, U8 value){asm volatile("lock xchgq %0,%1":"=r"(value),"=m"(addr[0]):"0"(value),"m"(addr[0]):"memory","cc");return value;}
#pragma endregion Thread Coherence
#pragma region Misc
#define byte_pos(pos) (pos * 8)
#define byte_shift(value,pos) (value << byte_pos(pos))
#define u4_byte_fill(value) byte_shift(value,0) | byte_shift(value,1) | byte_shift(value,2) | byte_shift(value,3)
enum {
Bitmask_3 = 0x00000007,
Bitmask_4 = 0x0000000f,
Bitmask_5 = 0x0000001f,
Bitmask_6 = 0x0000003f,
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,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 Struct_(DateTime) {
U4 micro_sec; // [0,999]
U4 msec; // [0,999]
U4 sec; // [0,60]
U4 min; // [0,59]
U4 hour; // [0,24]
U4 day; // [0,30]
WeekDay week_day;
Month month;
U4 year; // 1 = 1 CE, 0 = 1 BC
};
I_ DenseTime
dense_time_from_date_time(DateTime date_time) {
DenseTime result = 0;
result += date_time.year; result *= 12;
result += date_time.month; result *= 31;
result += date_time.day; result *= 24;
result += date_time.hour; result *= 60;
result += date_time.min; result *= 61;
result += date_time.sec; result *= 1000;
result += date_time.msec;
return(result);
}
#pragma endregion Misc
+72
View File
@@ -0,0 +1,72 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
#endif
typedef struct UnicodeDecode UnicodeDecode;
struct UnicodeDecode {
U4 inc;
U4 codepoint;
};
RO_ global U1 utf8_class[32] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5, };
FI_ void u64_to_hex(U8 val, char* buf, S4 chars) {
static const char hex_chars[] = "0123456789ABCDEF";
for(S1 i = chars - 1; i >= 0; --i) { buf[i] = hex_chars[val & 0xF]; val >>= 4; }
}
I_ UnicodeDecode
utf8_decode(U1* str, U1 max) {
UnicodeDecode result = {1, Max_U4};
U1 byte = str[0];
U1 byte_class = utf8_class[byte >> 3];
switch(byte_class) {
case 1: { result.codepoint = byte; } break;
case 2: if (1 < max) {
U1 cont_byte = str[1];
if(utf8_class[cont_byte >> 3] == 0) {
result.codepoint = (byte & Bitmask_5) << 6;
result.codepoint |= (cont_byte & Bitmask_6);
result.inc = 2;
}
} break;
case 3: if(2 < max) {
U1 cont_byte[2] = {str[1], str[2]};
if ( utf8_class[cont_byte[0] >> 3] == 0
&& utf8_class[cont_byte[1] >> 3] == 0) {
result.codepoint = (byte & Bitmask_4) << 12;
result.codepoint |= ((cont_byte[0] & Bitmask_6) << 6);
result.codepoint |= (cont_byte[1] & Bitmask_6);
result.inc = 3;
}
}break;
case 4: if(3 < max) {
U1 cont_byte[3] = {str[1], str[2], str[3]};
if ( utf8_class[cont_byte[0] >> 3] == 0
&& utf8_class[cont_byte[1] >> 3] == 0
&& utf8_class[cont_byte[2] >> 3] == 0) {
result.codepoint = (byte & Bitmask_3) << 18;
result.codepoint |= ((cont_byte[0] & Bitmask_6) << 12);
result.codepoint |= ((cont_byte[1] & Bitmask_6) << 6);
result.codepoint |= (cont_byte[2] & Bitmask_6);
result.inc = 4;
}
}
}
return result;
}
I_ U4
utf16_encode(U2* str, U4 codepoint) {
U4 inc = 1;
if (codepoint == Max_U4) { str[0] = (U2)'?'; }
else if (codepoint < 0x10000) { str[0] = (U2)codepoint; }
else {
U4 v = codepoint - 0x10000;
str[0] = Csafe_u2u4(0xD800 + (v >> 10));
str[1] = Csafe_u2u4(0xDC00 + (v & Bitmask_10));
inc = 2;
}
return inc;
}
+80
View File
@@ -0,0 +1,80 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "memory.h"
# include "math.h"
# include "text.h"
#
# if DUFFLE_WINDOWS
# include "win32.h"
# endif
#endif
CLANG_OPTIMIZE_DISABLE
// Most of this referenced from the RAD Debugger codebase.
typedef Enum_(U4,AccessFlags) {
Bit_(AccessFlag_Read, 0),
Bit_(AccessFlag_Write, 1),
Bit_(AccessFlag_Execute, 2),
Bit_(AccessFlag_Append, 3),
Bit_(AccessFlag_ShareRead, 4),
Bit_(AccessFlag_ShareWrite, 5),
Bit_(AccessFlag_Inherited, 6),
};
typedef U4 FilePropertyFlags;
enum {
Bit_(FilePropertyFlag_IsFolder, 0),
};
typedef Struct_(FileProperties) {
U8 size;
DenseTime modified;
DenseTime created;
FilePropertyFlags flags;
};
typedef Struct_(File) { U8 ptr[1]; };
FI_ File file_zero() { File f = {0}; return f; }
typedef Struct_(Scope_FileInfo) { File f; B4 once; };
FI_ B4 file_match(File a, File b) { return mem_match_struct(& a, & b); }
os_layer void file_close(File file);
os_layer File file_open(FArena* scratch, AccessFlags flags, Str8 path);
#define file_scope(scratch, flags, path) scope_info(Scope_FileInfo, {.f = file_open(scratch, flags, path)}, file_close(info.f))
os_layer FileProperties properties_from_file(File file);
os_layer U8 file_read (File file, R1_U8 rng, U1* out_data);
os_layer U8 file_write(File file, R1_U8 rng, U1* data);
I_ Slice_U1
data_from_file_range(FArena* arena, File file, R1_U8 range) {
U8 pre_pos = farena_save(arena[0]);
U8 len = span_r1u8(range);
Slice_U1 result = farena_push_array(arena, U1, len);
U8 actual_read_size = file_read(file, range, result.ptr); if (actual_read_size < result.len) {
U8 committed = align_pow2(actual_read_size, MEM_ALIGNMENT_DEFAULT);
farena_rewind(arena, pre_pos + committed); result.len = actual_read_size;
}
return result;
}
I_ Slice_U1
data_from_file_path(FArena* arena, Str8 path, FArena* scratch) { file_scope(scratch, AccessFlag_Read | AccessFlag_ShareRead, path) {
FileProperties props = properties_from_file(info.f);
Slice_U1 data = data_from_file_range(arena, info.f, r1u8(0, props.size)); return data;
} unreachable(); }
I_ B4
write_data_to_file_path(Str8 path, Str8 data, FArena* scratch) {
B4 good = false; file_scope(scratch, AccessFlag_Write, path) if (file_match(info.f, file_zero()) == false) {
U8 bytes_written = file_write(info.f, r1u8(0, data.len), data.ptr); good = bytes_written == data.len;
}
return good;
}
CLANG_OPTIMIZE_ENABLE
+18
View File
@@ -0,0 +1,18 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "memory.h"
# include "analysis.h"
#endif
#pragma region Hashing
FI_ void hash64_fnv1a(U8_R hash, Slice data, U8 seed) {
LP_ U8 const default_seed = 0xcbf29ce484222325;
if (seed == 0) seed = default_seed;
hash[0] = seed; for (U8 elem = data.ptr; elem != slice_end(data); elem += 1) {
hash[0] ^= u1_r(elem)[0];
hash[0] *= 0x100000001b3;
}
}
FI_ U8 hash64_fnv1a_ret(Slice data, U8 seed) { U8 h = 0; hash64_fnv1a(& h, data, seed); return h; }
#pragma endregion Hashing
+43
View File
@@ -0,0 +1,43 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "analysis.h"
#endif
#pragma region Math
#define u8_max 0xffffffffffffffffull
#define min(A,B) (((A) < (B)) ? (A) : (B))
#define max(A,B) (((A) > (B)) ? (A) : (B))
#define clamp_bot(X,B) max(X, B) // Clamp "X" by "B"
#define clamp_decrement(X) (((X) > 0) ? ((X) - 1) : 0)
typedef Struct_(R1_U1){ U1 p0; U1 p1; };
typedef Struct_(R1_U2){ U2 p0; U2 p1; };
typedef Struct_(R1_U4){ U4 p0; U2 p1; };
typedef Struct_(R1_U8){ U8 p0; U8 p1; };
#define r1u4(p0,p1) (R1_U4){p0,p1}
#define r1u8(p0,p1) (R1_U8){p0,p1}
typedef Struct_(V2_U1){ U1 x; U1 y;};
FI_ B8 add_of (U8 a, U8 b, U8*R_ res) { return __builtin_uaddll_overflow(a, b, res); }
FI_ B8 sub_of (U8 a, U8 b, U8*R_ res) { return __builtin_usubll_overflow(a, b, res); }
FI_ B8 mul_of (U8 a, U8 b, U8*R_ res) { return __builtin_umulll_overflow(a, b, res); }
FI_ B8 add_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_saddll_overflow(a, b, res); }
FI_ B8 sub_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_ssubll_overflow(a, b, res); }
FI_ B8 mul_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_smulll_overflow(a, b, res); }
FI_ U8 span_r1u8(R1_U8 r) {U8 c = ((r.p1 > r.p0) ? (r.p1 - r.p0) : 0); return c;}
#pragma endregion Math
#pragma region Numerics
enum {
Max_U4 = 0xffffffff
};
FI_ U2 Csafe_u2u4(U4 x) { assert_always(x <= Max_U4); return C_(U2, x); }
#pragma endregion Numerics
+158
View File
@@ -0,0 +1,158 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
#endif
#define MEM_ALIGNMENT_DEFAULT 4
#define assert_bounds(point, start, end) do{ \
assert((start) <= (point)); \
assert((point) <= (end)); \
} while(0)
I_ U8 align_pow2(U8 x, U8 b) {
assert(b != 0);
assert((b & (b - 1)) == 0); // Check power of 2
return ((x + b - 1) & (~(b - 1)));
}
#define align_struct(type_width) ((U8)(((type_width) + 3) & ~3))
FI_ void mem_bump_u4(U4 start, U4 cap, U4_R used, U4 amount) {
assert(amount <= (cap - used[0]));
used[0] += amount;
}
FI_ void mem_bump_u8(U8 start, U8 cap, U8_R used, U8 amount) {
assert(amount <= (cap - used[0]));
used[0] += amount;
}
#define mem_bump(start, cap, used, amount) _Generic(start, U4: mem_bump_u4, U8: mem_bump_u8)(start, cap, used, amount)
FI_ U8 mem_copy (U8 dest, U8 src, U8 len) { return (U8)(__builtin_memcpy ((void*)dest, (void const*)src, len)); }
FI_ U8 mem_copy_overlapping(U8 dest, U8 src, U8 len) { return (U8)(__builtin_memmove((void*)dest, (void const*)src, len)); }
FI_ U8 mem_fill (U8 dest, U8 value, U8 len) { return (U8)(__builtin_memset ((void*)dest, (int) value, len)); }
FI_ B4 mem_zero (U8 dest, U8 len) { if(dest == 0){return false;} mem_fill(dest, 0, len); return true; }
FI_ U8 mem_compare(U8 a, U8 b, U8 len) { return (U8)(__builtin_memcmp((void const*)a, (void const*)b, len)); }
FI_ B4 mem_match (U8 a, U8 b, U8 z) { return mem_compare(a, b, z) == 0; }
#define mem_match_struct(a,b) mem_match(C_(U8,a), C_(U8,b), S_((a)[0]))
#define mem_zero_struct(s) mem_zero(u8_(& s), S_(s))
I_ void mem_push_aligned_typed(U8 start, U8 capacity, U8_R used, U8 amount, U4 alignment, U4 type_width, U8_R out_ptr, U8_R out_len) {
if (amount == 0) { out_ptr[0] = 0; out_len[0] = 0; return; }
U8 desired = amount * (type_width == 0 ? 1 : type_width);
U8 to_commit = align_pow2(desired, alignment ? alignment : MEM_ALIGNMENT_DEFAULT);
U8 ptr = start + used[0];
mem_bump_u8(start, capacity, used, to_commit);
out_ptr[0] = ptr;
out_len[0] = to_commit;
}
#pragma region DAG
#define check_nil(nil, p) ((p) == 0 || (p) == nil)
#define set_nil(nil, p) ((p) = nil)
#define sll_stack_push_n(f, n, next) do { (n)->next = (f); (f) = (n); } while(0)
#define sll_queue_push_nz(nil, f, l, n, next) \
( \
check_nil(nil, f) ? ( \
(f) = (l) = (n), \
set_nil(nil, (n)->next) \
) \
: ( \
(l)->next=(n), \
(l) = (n), \
set_nil(nil,(n)->next) \
) \
)
#define sll_queue_push_n(f, l, n, next) sll_queue_push_nz(0, f, l, n, next)
#pragma endregion DAG
#pragma region Slice
typedef unsigned char TSet_(UTF8);
typedef Struct_(Str8) { UTF8* ptr; U8 len; }; typedef Str8 Slice_UTF8;
typedef Struct_(Slice_Str8) { Str8* ptr; U8 len; };
#define slit8(string_literal) ((Str8){ (UTF8*) string_literal, S_(string_literal) - 1 })
#define str8(p,l) (Str8){p,l}
typedef Struct_(Slice) { U8 ptr; U8 len; }; // Untyped Slice
FI_ Slice slice_ut_(U8 ptr, U8 len) { return (Slice){ptr, len}; }
#define Slice_(type) Struct_(tmpl(Slice,type)) { type* ptr; U8 len; }
#define slice_assert(s) do { assert((s).ptr != 0); assert((s).len > 0); } while(0)
#define slice_end(slice) ((slice).ptr + (slice).len)
#define S_slice(s) ((s).len * S_((s).ptr[0]))
#define slice_ut(ptr,len) slice_ut_(u8_(ptr), u8_(len))
#define slice_ut_arr(a) slice_ut_(u8_(a), S_(a))
#define slice_to_ut(s) slice_ut_(u8_((s).ptr), S_slice(s))
#define slice_iter(container, iter) (T_((container).ptr) iter = (container).ptr; iter != slice_end(container); ++ iter)
#define slice_arg_from_array(type, ...) & (tmpl(Slice,type)) { .ptr = Array_decl(type,__VA_ARGS__), .len = Array_len( Array_decl(type,__VA_ARGS__)) }
#define slice_from_array(type, array) (tmpl(Slice,type)) { .ptr = array, .len = S_(array) }
FI_ void slice_zero_(Slice s) { slice_assert(s); mem_zero(s.ptr, s.len); }
#define slice_zero(s) slice_zero_(slice_to_ut(s))
FI_ void slice_copy_(Slice dest, Slice src) {
assert(dest.len >= src.len);
slice_assert(dest);
slice_assert(src);
mem_copy(dest.ptr, src.ptr, src.len);
}
#define slice_copy(dest, src) do { \
static_assert(T_same(dest, src), "slices are not the same type"); \
slice_copy_(slice_to_ut(dest), slice_to_ut(src)); \
} while(0)
typedef Slice_(B1);
typedef Slice_(U1);
typedef Slice_(U2);
typedef Slice_(U4);
typedef Slice_(U8);
#pragma endregion Slice
#pragma region FArena
typedef Opt_(farena) { U8 alignment, type_width; };
typedef Struct_(FArena) { U8 start, capacity, used; };
FI_ void farena_init(FArena_R arena, Slice mem) { assert(arena != nullptr);
arena->start = mem.ptr;
arena->capacity = mem.len;
arena->used = 0;
}
FI_ FArena farena_make(Slice mem) { FArena a; farena_init(& a, mem); return a; }
FI_ Slice farena_push(FArena_R arena, U8 amount, Opt_farena o) { Slice res;
mem_push_aligned_typed(arena->start, arena->capacity, & arena->used, amount, o.alignment, o.type_width
, & res.ptr, & res.len);
return res;
}
FI_ void farena_reset (FArena_R arena) { arena->used = 0; }
FI_ void farena_rewind(FArena_R arena, U8 save_point) {
assert(save_point <= arena->used);
arena->used = save_point;
}
FI_ U8 farena_save(FArena arena) { return arena.used; }
#define farena_push_(arena, amount, ...) farena_push((arena),(amount),opt_(farena,__VA_ARGS__))
#define farena_push_type(arena, type, ...) C_(type*,farena_push((arena),1, opt_(farena,.type_width=S_(type),__VA_ARGS__)).ptr)
#define farena_push_array(arena, type, amount, ...) (tmpl(Slice,type)){ C_(type*,farena_push((arena),(amount),opt_(farena,.type_width=S_(type),__VA_ARGS__)).ptr),(amount) }
#pragma endregion FArena
#pragma region FStack
#define FStack_(name, type, width) Struct_(name) { U8 top; type arr[width]; }
FI_ Slice fstack_push(Slice mem, U8_R top, U8 amount, Opt_farena o) { Slice res;
mem_push_aligned_typed(mem.ptr, mem.len, top, amount, o.alignment, o.type_width
, & res.ptr, & res.len);
return res;
};
// This is here more for annotation than anything else.
#define fstack_save(stack) stack.top
#define fstack_rewind(stack, sp) do{stack.top = sp;}while(0)
#define fstack_reset(stack) do{stack.top = 0; }while(0)
#define fstack_slice(stack) slice_ut_arr((stack).arr)
#define fstack_push_(stk, amount, ...) fstack_push(fstack_slice(stk),&(stk).top,(amount),opt_(farena,__VA_ARGS__))
#define fstack_push_array(stk, type, amount, ...) (tmpl(Slice,type)){ C_(type*,fstack_push(fstack_slice(stk),&(stk).top,(amount),opt_(farena,.type_width=S_(type),__VA_ARGS__)).ptr),(amount) }
#pragma endregion FStack
+55
View File
@@ -0,0 +1,55 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "asm.h"
# include "memory.h"
# include "hashing.h"
# include "analysis.h"
#endif
#pragma region Key Table Linear (KTL)
enum { KT_Slot_value = S_(U8), };
#define KTL_Slot_(type) Struct_(tmpl(KTL_Slot,type)) { \
U8 key; \
type value; \
}
#define KTL_(type) Slice_(tmpl(KTL_Slot,type)); \
typedef tmpl(Slice_KTL_Slot,type) tmpl(KTL,type)
typedef Slice KTL_Byte;
typedef Struct_(KTL_Meta) {
U8 slot_size;
U8 type_width;
};
typedef Array_(Str8, 2);
typedef Slice_(A2_Str8);
typedef KTL_Slot_(Str8);
typedef KTL_(Str8);
FI_ void ktl_populate_slice_a2_str8(KTL_Str8* kt, Slice_A2_Str8 values) {
assert(kt != null); slice_assert(* kt);
if (values.len == 0) return;
assert(kt->len == values.len);
for index_iter(U4, id, 0, <, values.len) {
hash64_fnv1a(& kt->ptr[id].key, slice_to_ut(values.ptr[id][0]), 0);
mem_copy(u8_(& kt->ptr[id].value), u8_(& values.ptr[id][1]), S_(Str8));
}
}
#define ktl_str8_key(str) hash64_fnv1a_ret(slice_to_ut(slit8(str)), 0)
#define ktl_str8_from_arr(arr) (KTL_Str8){arr, Array_len(arr)}
FI_ Str8_R ktl_str8_find(KTL_Str8 table, U8 key) {
U8 i = 0;
while (table.len - i >= 4) {
KTL_Slot_Str8_R p = table.ptr + i;
U4 mask = find_aos_keys_mask_u8x4(& p[0].key, & p[1].key, & p[2].key, & p[3].key, key);
if (mask) return & table.ptr[i + C_(U8, count_trailing_zeros_u4(mask))].value;
i += 4;
}
while (i < table.len) {
if (table.ptr[i].key == key) return & table.ptr[i].value;
++ i;
}
assert(false);
return nullptr;
}
#pragma endregion KTL
+231
View File
@@ -0,0 +1,231 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "memory.h"
# include "encoding.h"
# include "hashing.h"
# include "tables.h"
# include "analysis.h"
# include "asm.h"
#endif
// NOTE(rjf): Includes reverses for uppercase and lowercase hex.
RO_ U8 integer_symbol_reverse[128] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
FI_ B4 char_is_upper(UTF8 c) { return('A' <= c && c <= 'Z'); }
FI_ UTF8 char_to_lower(UTF8 c) { if (char_is_upper(c)) { c += ('a' - 'A'); } return(c); }
FI_ B4 char_is_digit(UTF8 c, U4 base) {
B4 result = 0; if (0 < base && base <= 16) {
if (integer_symbol_reverse[c] < base) result = 1;
}
return result;
}
FI_ UTF8 integer_symbols(UTF8 value) {
LP_ UTF8 lookup_table[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', };
return lookup_table[C_(UTF8, value)];
}
FI_ U8 u8_from_str8(Str8 str, U4 radix) {
U8 x = 0; if(1 < radix && radix <= 16) {
for each_iter(U8, cursor, str.len) {
x *= radix;
x += integer_symbol_reverse[str.ptr[cursor] & 0x7F];
}
}
return x;
}
typedef Struct_(Info_str8_from_u4) {
Str8 prefix;
U4 digit_group_size;
U4 needed_leading_zeros;
U4 size_required;
};
I_ Info_str8_from_u4 str8_from_u4_info(U4 num, U4 radix, U4 min_digits, U4 digit_group_separator)
{
Info_str8_from_u4 info = {0};
LP_ Str8 tbl_prefix[] = { slit8("0x"), slit8("0o"), slit8("0b") };
switch (radix) {
case 16: { info.prefix = tbl_prefix[0]; } break;
case 8: { info.prefix = tbl_prefix[1]; } break;
case 2: { info.prefix = tbl_prefix[2]; } break;
}
info.digit_group_size = 3;
switch (radix) {
default: break;
case 2:
case 8:
case 16: {
info.digit_group_size = 4;
}
break;
}
info.needed_leading_zeros = 0;
{
U4 needed_digits = 1;
{
U4 u32_reduce = num;
for(;;)
{
u32_reduce /= radix;
if (u32_reduce == 0) {
break;
}
needed_digits += 1;
}
}
info.needed_leading_zeros = (min_digits > needed_digits) ? min_digits - needed_digits : 0;
U4 needed_separators = 0;
if (digit_group_separator != 0)
{
needed_separators = (needed_digits + info.needed_leading_zeros) / info.digit_group_size;
if (needed_separators > 0 && (needed_digits + info.needed_leading_zeros) % info.digit_group_size == 0) {
needed_separators -= 1;
}
}
info.size_required = info.prefix.len + info.needed_leading_zeros + needed_separators + needed_digits;
}
return info;
}
I_ Str8 str8_from_u4_buf(Slice buf, U4 num, U4 radix, U4 min_digits, U4 digit_group_separator, Info_str8_from_u4 info)
{
assert(buf.len >= info.size_required);
Str8 result = { C_(UTF8*, buf.ptr), info.size_required };
/*Fill Content*/ {
U4 num_reduce = num;
U4 digits_until_separator = info.digit_group_size;
for (U8 idx = 0; idx < result.len; idx += 1)
{
U8 separator_pos = result.len - idx - 1;
if (digits_until_separator == 0 && digit_group_separator != 0) {
result.ptr[separator_pos] = u1_(digit_group_separator);
digits_until_separator = info.digit_group_size + 1;
}
else {
result.ptr[separator_pos] = (U1) char_to_lower(integer_symbols(u1_(num_reduce % radix)));
num_reduce /= radix;
}
digits_until_separator -= 1;
if (num_reduce == 0) break;
}
for (U8 leading_0_idx = 0; leading_0_idx < info.needed_leading_zeros; leading_0_idx += 1) {
result.ptr[info.prefix.len + leading_0_idx] = '0';
}
}
/*Fill Prefix*/ if (info.prefix.len > 0) { slice_copy(result, info.prefix); }
return result;
}
I_ Str8 str8_fmt_ktl_buf(Slice buffer, KTL_Str8 table, Str8 fmt_template){
slice_assert(buffer);
slice_assert(table);
slice_assert(fmt_template);
UTF8_R cursor_buffer = C_(UTF8_R, buffer.ptr);
U8 buffer_remaining = buffer.len;
UTF8_R cursor_fmt = fmt_template.ptr;
U8 left_fmt = fmt_template.len;
U1x16 needle_lt = splat_u4_u1x16(u4_byte_fill('<'));
U1x16 needle_gt = splat_u4_u1x16(u4_byte_fill('>'));
while (left_fmt && buffer_remaining)
{
// Forward until we hit the delimiter '<' or the template's contents are exhausted.
U8 copy_offset = 0;
if (cursor_fmt[0] == '<') {
UTF8_R sig = cursor_fmt + 1;
U8 sig_max = slice_end(fmt_template) - sig;
U8 sig_len = find_u1_via_u1x16(sig, sig_max, '>', needle_gt);
assert(sig_len < sig_max);
Str8_R value = ktl_str8_find(table, hash64_fnv1a_ret(slice_ut(sig, sig_len), 0));
U8 n = min(buffer_remaining, value->len);
assert((buffer_remaining - n) > 0); mem_copy(u8_(cursor_buffer), u8_(value->ptr), n);
cursor_buffer += n;
buffer_remaining -= n;
cursor_fmt = sig + sig_len + 1;
left_fmt -= sig_len + 2;
continue;
}
U8 n = find_u1_via_u1x16(cursor_fmt, min(left_fmt, buffer_remaining), '<', needle_lt);
assert((buffer_remaining - 1) > 0); n = min(buffer_remaining, n);
mem_copy(u8_(cursor_buffer), u8_(cursor_fmt), n);
cursor_buffer += n;
cursor_fmt += n;
buffer_remaining -= n;
left_fmt -= n;
}
return str8(C_(UTF8*,buffer.ptr), buffer.len - buffer_remaining);
}
typedef Struct_(Str8Gen) { UTF8* ptr; U8 cap, len; };
FI_ Str8Gen str8gen_make(Slice s) { return (Str8Gen){C_(UTF8*,s.ptr), s.len, 0}; }
FI_ Slice str8gen_buf(Str8Gen_R gen) { return (Slice){u8_(gen->ptr) + gen->len, gen->cap - gen->len}; }
FI_ void str8gen_append_str8(Str8Gen_R gen, Str8 str) { assert(gen != nullptr);
U8 ptr = u8_(gen->ptr) + gen->len;
mem_bump_u8(u8_(gen->ptr), gen->cap, & gen->len, str.len);
mem_copy(ptr, u8_(str.ptr), str.len);
}
FI_ void str8gen_append_fmt(Str8Gen_R gen, Str8 fmt, KTL_Str8 tbl) {
Str8 result = str8_fmt_ktl_buf(str8gen_buf(gen), tbl, fmt);
gen->len += result.len;
}
#define str8gen_append_str8_(gen, s) str8gen_append_str8(gen, str8(s))
// Dealing with Wides (UTF16)
typedef U4 UTF16;
typedef Struct_(Str16) { UTF16* ptr; U8 len; };
typedef Str16 Slice_UTF16;
#define str16(p,l) (Str16){p,l}
internal Str16
str16_from_8(FArena* arena, Str8 in) {
Str16 result = {0}; if (in.len) {
U8 pre_pos = farena_save(arena[0]);
U8 cap = in.len * 2;
Slice_U2 str = farena_push_array(arena, U2, cap + 1);
U1* ptr = in.ptr;
U1* opl = ptr + in.len;
U8 size = 0;
UnicodeDecode consume;
for(;ptr < opl; ptr += consume.inc) {
consume = utf8_decode(ptr, opl - ptr);
size += utf16_encode(str.ptr + size, consume.codepoint);
}
str.ptr[size] = 0;
U8 committed = align_pow2((size + 1) * S_(U2), MEM_ALIGNMENT_DEFAULT);
farena_rewind(arena, pre_pos + committed);
result = str16(C_(UTF16*, str.ptr), size);
}
return result;
}
// Formatter where serial operation is done on-demand per-entry.
// enum {
// KTL_Str8FmtEntry_InlaidSize = (S_(Str8) * 2) - S_(Str8Fmt_TokenKind),
// };
// typedef Enum_(U4, Str8Fmt_SerialOpKind) {
// Str8Fmt_TKind_Str8,
// Str8Fmt_Base16_U1,
// Str8Fmt_Base16_U2,
// Str8Fmt_Base10_U4,
// };
// typedef Struct_(KTL_Str8Fmt_SerialOp_Entry) {
// union {
// U1 InlaidData[KTL_Str8FmtEntry_InlaidSize];
// Str8 str;
// void* Ptr;
// };
// Str8Fmt_SerialOpKind kind;
// };
// typedef KTL_Slot_(KTL_Str8Fmt_SerialOp_Entry);
+335
View File
@@ -0,0 +1,335 @@
#if INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "memory.h"
# include "files.h"
#endif
WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess"); // Kernel 32
#pragma region IO
enum {
MS_STD_INPUT_CODE = u4_(-10),
MS_STD_OUTPUT_CODE = u4_(-11),
#define MS_STD_INPUT u4_(MS_STD_INPUT_CODE)
#define MS_STD_OUTPUT u4_(MS_STD_OUTPUT_CODE)
};
typedef Struct_(MS_Handle){U8 id;};
#pragma endregion IO
// --- WinAPI Minimal Definitions ---
typedef Struct_(MS_OVERLAPPED) {
void* Internal;
void* InternalHigh;
union {
struct {
U4 Offset;
U4 OffsetHigh;
};
void* Pointer;
};
MS_Handle hEvent;
};
typedef Struct_(MS_SECURITY_ATTRIBUTES) {
U4 nLength;
void* lpSecurityDescriptor;
B4 bInheritHandle;
};
typedef struct MS_SYSTEMTIME {
U2 wYear;
U2 wMonth;
U2 wDayOfWeek;
U2 wDay;
U2 wHour;
U2 wMinute;
U2 wSecond;
U2 wMilliseconds;
} MS_SYSTEMTIME;
typedef struct MS_FILETIME {
U4 dwLowDateTime;
U4 dwHighDateTime;
} MS_FILETIME;
typedef struct MS_BY_HANDLE_FILE_INFORMATION {
U4 dwFileAttributes;
MS_FILETIME ftCreationTime;
MS_FILETIME ftLastAccessTime;
MS_FILETIME ftLastWriteTime;
U4 dwVolumeSerialNumber;
U4 nFileSizeHigh;
U4 nFileSizeLow;
U4 nNumberOfLinks;
U4 nFileIndexHigh;
U4 nFileIndexLow;
} MS_BY_HANDLE_FILE_INFORMATION;
typedef struct MS_WNDCLASSA {
U4 style;
S8 (*lpfnWndProc)(void*, U4, U8, S8);
S4 cbClsExtra;
S4 cbWndExtra;
void* hInstance;
void* hIcon;
void* hCursor;
void* hbrBackground;
char const* lpszMenuName;
char const* lpszClassName;
} MS_WNDCLASSA;
typedef struct MS_POINT { S4 x, y; } MS_POINT;
typedef struct MS_MSG { void* hwnd; U4 message; U8 wParam; S8 lParam; U4 time; MS_POINT pt; } MS_MSG;
typedef struct MS_RECT { S4 left, top, right, bottom; } MS_RECT;
typedef struct MS_PAINTSTRUCT { void* hdc; S4 fErase; MS_RECT rcPaint; S4 fRestore; S4 fIncUpdate; U1 rgbReserved[32]; } MS_PAINTSTRUCT;
// --- Kernel32 ---
WinAPI U4 ms_get_last_error() asm("GetLastError");
WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess");
WinAPI MS_Handle ms_get_std_handle(U4 handle_type) asm("GetStdHandle");
WinAPI void* ms_virtual_alloc(void* lpAddress, U8 dwSize, U4 flAllocationType, U4 flProtect) asm("VirtualAlloc");
WinAPI B4 ms_read_console(
MS_Handle handle,
UTF8_R buffer,
U4 to_read,
U4_R num_read,
U8 reserved_input_control
) asm("ReadConsoleA");
WinAPI B4 ms_write_console(
MS_Handle handle,
UTF8 const*R_ buffer,
U4 chars_to_write,
U4_V chars_written,
U8 reserved
) asm("WriteConsoleA");
WinAPI B4 ms_get_file_information_by_handle(MS_Handle* handle, MS_BY_HANDLE_FILE_INFORMATION* file_information) asm("GetFileInformationByHandle");
WinAPI MS_Handle* ms_create_file_a(char const* lpFileName, U4 dwDesiredAccess, U4 dwShareMode, void* lpSecurityAttributes, U4 dwCreationDisposition, U4 dwFlagsAndAttributes, void* hTemplateFile) asm("CreateFileA");
WinAPI MS_Handle* ms_create_file_w(U2 const* lpFileName, U4 dwDesiredAccess, U4 dwShareMode, void* lpSecurityAttributes, U4 dwCreationDisposition, U4 dwFlagsAndAttributes, void* hTemplateFile) asm("CreateFileW");
WinAPI B4 ms_write_file(void* hFile, void const* lpBuffer, U4 nNumberOfBytesToWrite, U4* lpNumberOfBytesWritten, void* lpOverlapped) asm("WriteFile");
WinAPI B4 ms_read_file(MS_Handle* hFile, void* lpBuffer, U4 nNumberOfBytesToRead, U4* lpNumberOfBytesRead, void* lpOverlapped) asm("ReadFile");
WinAPI B4 ms_close_handle(void* hObject) asm("CloseHandle");
WinAPI B4 ms_filetime_to_systemtime(void const* lpFileTime, void* lpSystemTime) asm("FileTimeToSystemTime");
// --- User32 ---
WinAPI U2 ms_register_class_a(MS_WNDCLASSA const* lpWndClass) asm("RegisterClassA");
WinAPI void* ms_create_window_ex_a(
U4 dwExStyle,
char const* lpClassName,
char const* lpWindowName,
U4 dwStyle,
S4 X,
S4 Y,
S4 nWidth,
S4 nHeight,
void* hWndParent,
void* hMenu,
void* hInstance,
void* lpParam
) asm("CreateWindowExA");
WinAPI S4 ms_show_window(void* hWnd, S4 nCmdShow) asm("ShowWindow");
WinAPI S4 ms_get_message_a(MS_MSG* lpMsg, void* hWnd, U4 wMsgFilterMin, U4 wMsgFilterMax) asm("GetMessageA");
WinAPI S4 ms_translate_message(MS_MSG const* lpMsg) asm("TranslateMessage");
WinAPI S8 ms_dispatch_message_a(MS_MSG const* lpMsg) asm("DispatchMessageA");
WinAPI S8 ms_def_window_proc_a(void* hWnd, U4 Msg, U8 wParam, S8 lParam) asm("DefWindowProcA");
WinAPI void ms_post_quit_message(S4 nExitCode) asm("PostQuitMessage");
WinAPI S4 ms_invalidate_rect(void* hWnd, MS_RECT const* lpRect, S4 bErase) asm("InvalidateRect");
WinAPI S2 ms_get_async_key_state(S4 vKey) asm("GetAsyncKeyState");
// --- GDI32 ---
WinAPI void* ms_begin_paint(void* hWnd, MS_PAINTSTRUCT* lpPaint) asm("BeginPaint");
WinAPI S4 ms_end_paint(void* hWnd, MS_PAINTSTRUCT const* lpPaint) asm("EndPaint");
WinAPI U4 ms_set_text_color(void* hdc, U4 color) asm("SetTextColor");
WinAPI U4 ms_set_bk_color(void* hdc, U4 color) asm("SetBkColor");
WinAPI S4 ms_text_out_a(void* hdc, S4 x, S4 y, char const* lpString, S4 c) asm("TextOutA");
WinAPI void* ms_get_stock_object(S4 i) asm("GetStockObject");
WinAPI void* ms_create_font_a(
S4 cHeight,
S4 cWidth,
S4 cEscapement,
S4 cOrientation,
S4 cWeight,
U4 bItalic,
U4 bUnderline,
U4 bStrikeOut,
U4 iCharSet,
U4 iOutPrecision,
U4 iClipPrecision,
U4 iQuality,
U4 iPitchAndFamily,
char const* pszFaceName
) asm("CreateFontA");
WinAPI void* ms_create_compatible_dc(void* hdc) asm("CreateCompatibleDC");
WinAPI void* ms_create_compatible_bitmap(void* hdc, S4 cx, S4 cy) asm("CreateCompatibleBitmap");
WinAPI B4 ms_bit_blt(void* hdcDest, S4 x, S4 y, S4 w, S4 h, void* hdcSrc, S4 xSrc, S4 ySrc, U4 rop) asm("BitBlt");
WinAPI B4 ms_delete_dc(void* hdc) asm("DeleteDC");
WinAPI B4 ms_get_client_rect(void* hwnd, MS_RECT* lpRect) asm("GetClientRect");
WinAPI void* ms_select_object(void* hdc, void* h) asm("SelectObject");
WinAPI S4 ms_rectangle(void* hdc, S4 left, S4 top, S4 right, S4 bottom) asm("Rectangle");
WinAPI S4 ms_set_bk_mode(void* hdc, S4 mode) asm("SetBkMode");
WinAPI void* ms_create_solid_brush(U4 color) asm("CreateSolidBrush");
WinAPI S4 ms_delete_object(void* ho) asm("DeleteObject");
#define MS_INVALID_HANDLE_VALUE ((MS_Handle*)(U8) - 1)
enum {
MS_GENERIC_READ = 0x80000000,
MS_GENERIC_WRITE = 0x40000000,
MS_GENERIC_EXECUTE = 0x20000000L,
MS_CREATE_ALWAYS = 2,
MS_OPEN_EXISTING = 3,
MS_OPEN_ALWAYS = 4,
MS_FILE_APPEND_DATA = 0x0004,
MS_FILE_ATTRIBUTE_NORMAL = 0x80,
MS_FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
MS_FILE_SHARE_READ = 0x00000001,
MS_FILE_SHARE_WRITE = 0x00000002,
MS_FILE_SHARE_DELETE = 0x00000004,
MS_MEM_COMMIT = 0x00001000,
MS_MEM_RESERVE = 0x00002000,
MS_PAGE_READWRITE = 0x04,
MS_SRCCOPY = 0x00CC0020,
MS_WM_DESTROY = 0x0002,
MS_WM_SIZE = 0x0005,
MS_WM_PAINT = 0x000F,
MS_WM_ERASEBKGND = 0x0014,
MS_WM_KEYDOWN = 0x0100,
MS_WM_KEYUP = 0x0101,
MS_WM_MOUSEMOVE = 0x0200,
MS_WM_LBUTTONDOWN = 0x0201,
MS_WM_LBUTTONUP = 0x0202,
MS_WM_RBUTTONDOWN = 0x0204,
MS_WM_RBUTTONUP = 0x0205,
MS_WM_MBUTTONDOWN = 0x0207,
MS_WM_MBUTTONUP = 0x0208,
MS_WM_MOUSEWHEEL = 0x020A,
MS_WS_OVERLAPPEDWINDOW = 0x00CF0000,
MS_WS_VISIBLE = 0x10000000,
MS_PAGE_EXECUTE_READWRITE = 0x40,
MS_VK_BACK = 0x08,
MS_VK_TAB = 0x09,
MS_VK_RETURN = 0x0D,
MS_VK_SHIFT =0x10,
MS_VK_SPACE = 0x20,
MS_VK_PRIOR = 0x21,
MS_VK_NEXT = 0x22,
MS_VK_LEFT = 0x25,
MS_VK_UP = 0x26,
MS_VK_RIGHT = 0x27,
MS_VK_DOWN = 0x28,
MS_VK_F1 = 0x70,
MS_VK_F2 = 0x71,
MS_VK_F5 = 0x74,
MS_WM_CHAR = 0x0102,
};
#if BUILD_DEBUG
FI_ void assert(U8 cond) { if(cond){return;} else{debug_trap(); ms_exit_process(1);} }
#endif
// Layer Implementation
#if DUFFLE_WINDOWS
I_ void
w32_date_time_from_system_time(DateTime* out, MS_SYSTEMTIME* in) {
out->year = in->wYear;
out->month = in->wMonth - 1;
out->week_day = in->wDayOfWeek;
out->day = in->wDay;
out->hour = in->wHour;
out->min = in->wMinute;
out->sec = in->wSecond;
out->msec = in->wMilliseconds;
}
I_ void
w32_dense_time_from_file_time(DenseTime* out, MS_FILETIME* in) {
MS_SYSTEMTIME systime = {0}; ms_filetime_to_systemtime(in, &systime); DateTime date_time = {0};
w32_date_time_from_system_time(&date_time, &systime); out[0] = dense_time_from_date_time(date_time);
}
I_ FilePropertyFlags
w32_file_property_flags_from_dwFileAttributes(U4 dwFileAttributes) {
FilePropertyFlags flags = 0; if (dwFileAttributes & MS_FILE_ATTRIBUTE_DIRECTORY) { flags |= FilePropertyFlag_IsFolder; } return flags;
}
I_ FileProperties
properties_from_file(File file) {
if (file_match(file, file_zero())) { FileProperties r = {0}; return r; }
FileProperties props = {0}; MS_Handle* handle = C_(MS_Handle*,file.ptr[0]);
MS_BY_HANDLE_FILE_INFORMATION info; S4 info_good = ms_get_file_information_by_handle(handle, &info);
if (info_good) {
U4 size_lo = info.nFileSizeLow; U4 size_hi = info.nFileSizeHigh;
props.size = C_(U8,size_lo) | (C_(U8,size_hi)<<32);
w32_dense_time_from_file_time(& props.modified, & info.ftLastWriteTime);
w32_dense_time_from_file_time(& props.created, & info.ftCreationTime);
props.flags = w32_file_property_flags_from_dwFileAttributes(info.dwFileAttributes);
}
return props;
}
internal File
file_open(FArena* scratch, AccessFlags flags, Str8 path) {
File result = {0};
U8 scratch_at = farena_save(scratch[0]);
Str16 path16 = str16_from_8(scratch, path);
U4 access_flags = 0;
U4 share_mode = 0;
U4 creation_disposition = MS_OPEN_EXISTING;
MS_SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0};
if (flags & AccessFlag_Read) { access_flags |= MS_GENERIC_READ; }
if (flags & AccessFlag_Write) { access_flags |= MS_GENERIC_WRITE; }
if (flags & AccessFlag_Execute) { access_flags |= MS_GENERIC_EXECUTE; }
if (flags & AccessFlag_ShareRead) { share_mode |= MS_FILE_SHARE_READ; }
if (flags & AccessFlag_ShareWrite) { share_mode |= MS_FILE_SHARE_WRITE | MS_FILE_SHARE_DELETE; }
if (flags & AccessFlag_Write) { creation_disposition = MS_CREATE_ALWAYS; }
if (flags & AccessFlag_Append) { creation_disposition = MS_OPEN_ALWAYS; access_flags |= MS_FILE_APPEND_DATA; }
if (flags & AccessFlag_Inherited) { security_attributes.bInheritHandle = 1; }
MS_Handle* file = ms_create_file_w(C_(U2 const*,path16.ptr), access_flags, share_mode, &security_attributes, creation_disposition, MS_FILE_ATTRIBUTE_NORMAL, 0);
if(file != MS_INVALID_HANDLE_VALUE) { result.ptr[0] = C_(U8,file); }
else {
U4 err = ms_get_last_error(); (void)err;
}
farena_rewind(scratch, scratch_at);
return result;
}
internal void file_close(File file) {
if(file_match(file, file_zero())) { return; }
MS_Handle* handle = C_(MS_Handle*,file.ptr[0]);
B4 result = ms_close_handle(handle); (void)result;
}
internal U8 file_read(File file, R1_U8 rng, U1* out_data) {
if (file_match(file, file_zero())) { return 0; }
MS_Handle* handle = C_(MS_Handle*,file.ptr[0]);
U1* ptr = out_data;
U8 off = rng.p0; while (off != rng.p1) {
U8 amt64 = rng.p1 - off;
U4 amt32 = C_(U4, min(mega(32), amt64));
U4 read_size = 0;
MS_OVERLAPPED overlapped = { .Offset = C_(U4,off), .OffsetHigh = (U4)(off >> 32) };
if( ! ms_read_file(handle, ptr, amt32, &read_size, &overlapped)) { break; }
ptr += read_size;
off += read_size;
}
U8 total_read_size = off - rng.p0; return total_read_size;
}
internal U8 file_write(File file, R1_U8 rng, U1* data) {
if (file_match(file, file_zero())) { return 0; }
MS_Handle* handle = C_(MS_Handle*,file.ptr[0]);
U1 const* ptr = data;
U8 off = rng.p0; while (off != rng.p1) {
U8 amt64 = rng.p1 - off;
U4 amt32 = C_(U4, min(mega(32), amt64));
U4 write_size = 0;
MS_OVERLAPPED overlapped = { .Offset = C_(U4,off), .OffsetHigh = C_(U4,off >> 32) };
if ( ! ms_write_file(handle, ptr, amt32, & write_size, & overlapped) || write_size == 0) { break; }
ptr += write_size;
off += write_size;
}
return off - rng.p0;
}
#endif
+87
View File
@@ -0,0 +1,87 @@
#include "duffle/dsl.h"
#include "duffle/analysis.h"
#include "duffle/math.h"
#include "duffle/memory.h"
#include "duffle/hashing.h"
#include "duffle/encoding.h"
#include "duffle/tables.h"
#include "duffle/text.h"
#include "duffle/files.h"
#include "duffle/win32.h"
// #include "8086/decoder.h"
typedef Struct_(U2_HL) { U1 Low; U1 High; };
#define bitmask_(pos) (1 << pos)
#define bit_isolate(bitfield, pos) (bitmask_(pos) & value)
#define serialize_bit(bitfield, pos) (bit_isolate(bitfield, pos) == bitmask_(pos) ? '1' : '0')
typedef Enum_(U4, Endieaness) {
Little,
Big,
};
FI_ void a8utf8_from_u1_le(UTF8 out[8], U1 value) {
out[0] = serialize_bit(value, 7);
out[1] = serialize_bit(value, 6);
out[2] = serialize_bit(value, 5);
out[3] = serialize_bit(value, 4);
out[4] = serialize_bit(value, 3);
out[5] = serialize_bit(value, 2);
out[6] = serialize_bit(value, 1);
out[7] = serialize_bit(value, 0);
}
FI_ void a8utf8_from_u1_be(UTF8 out[8], U1 value) {
out[0] = serialize_bit(value, 0);
out[1] = serialize_bit(value, 1);
out[2] = serialize_bit(value, 2);
out[3] = serialize_bit(value, 3);
out[4] = serialize_bit(value, 4);
out[5] = serialize_bit(value, 5);
out[6] = serialize_bit(value, 6);
out[7] = serialize_bit(value, 7);
}
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};
U4 req_len = data.len * 8; jump_lt(str8_mem->capacity,req_len, jret);
result = farena_push_array(str8_mem, UTF8, req_len);
for index_iter(U4,cursor, 0,<,req_len) { a8utf8_from_u1_le(result.ptr + cursor, data.ptr[cursor]); }
jret: return result;
}
enum {
Scratchpad_Len = kilo(1),
FileRam_Len = kilo(16),
};
typedef Struct_(SMemory) {
U1 Scratchpad [Scratchpad_Len];
U1 FileRam [FileRam_Len];
};
global SMemory smem;
#define path_course_content "./course_content/perfaware/"
#define path_part1 path_course_content "part1/"
CLANG_OPTIMIZE_DISABLE
int main()
{
FArena scratch = farena_make(slice_ut_arr(smem.Scratchpad));
FArena file_arena = farena_make(slice_ut_arr(smem.FileRam));
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");
Slice_U1 data = data_from_file_path(& file_arena, path_listing_0037_single_register_mov, & scratch);
ms_exit_process(0);
return 0;
}
CLANG_OPTIMIZE_ENABLE
Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

-208
View File
@@ -1,208 +0,0 @@
#if __clang__
# pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wswitch"
# pragma clang diagnostic ignored "-Wunused-variable"
#endif
#pragma region ZPL INCLUDE
#if __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wmissing-braces"
# pragma clang diagnostic ignored "-Wbraced-scalar-init"
#endif
#define ZPL_IMPLEMENTATION
// # define ZPL_HEAP_ANALYSIS
# define ZPL_NO_MATH_H
# define ZPL_CUSTOM_MODULES
# define ZPL_MODULE_ESSENTIALS
# define ZPL_MODULE_CORE
# define ZPL_MODULE_TIMER
// # define ZPL_MODULE_HASHING
// # define ZPL_MODULE_REGEX
// # define ZPL_MODULE_EVENT
// # define ZPL_MODULE_DLL
// # define ZPL_MODULE_OPTS
// # define ZPL_MODULE_PROCESS
// # define ZPL_MODULE_MATH
// # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER
// extern "C" {
#include "zpl.h"
// }
#if __clang__
# pragma clang diagnostic pop
#endif
#pragma endregion ZPL INCLUDE
zpl_arena Global_Arena {};
#define g_allocator zpl_arena_allocator( & Global_Arena)
void setup()
{
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) );
if ( Global_Arena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void cleanup()
{
zpl_arena_free( & Global_Arena);
}
#pragma region ZPL Expose
zpl_string string_make(zpl_isize capacity)
{
zpl_isize header_size = zpl_size_of(zpl_string_header);
void *ptr = zpl_alloc(g_allocator, header_size + capacity + 1);
zpl_string str;
zpl_string_header *header;
if (ptr == NULL) return NULL;
zpl_zero_size(ptr, header_size + capacity + 1);
str = cast(char *) ptr + header_size;
header = ZPL_STRING_HEADER(str);
header->allocator = g_allocator;
header->length = 0;
header->capacity = capacity;
str[capacity] = '\0';
return str;
}
inline
zpl_string string_make(const char *str)
{
zpl_isize len = str ? zpl_strlen(str) : 0;
return zpl_string_make_length(g_allocator, str, len);
}
inline
zpl_string string_append(zpl_string str, zpl_string const other)
{
return zpl_string_append_length(str, other, zpl_string_length(other));
}
zpl_string string_format( char const* fmt, ... )
{
zpl_local_persist zpl_thread_local char buf[ZPL_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buf);
}
zpl_string string_format( char* buffer, zpl_isize size, char const* fmt, ... )
{
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buffer, size, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buffer);
}
#pragma endregion ZPL Expose
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
#undef cast
#define cast( Type_ , Value_ ) ( ( Type_ )( Value_ ) )
#define ct constexpr
#define gen( ... ) template< __VA_ARGS__ >
#define forceinline ZPL_ALWAYS_INLINE
#define print_nl( _) zpl_printf("\n")
#define Msg_Invalid_Value "INVALID VALUE PROVIDED"
#define scast static_cast
#define rcast reinterpret_cast
#define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) )
using s8 = zpl_i8;
using u8 = zpl_u8;
using u16 = zpl_u16;
using u32 = zpl_u32;
using f64 = zpl_f64;
using uw = zpl_usize;
using sw = zpl_isize;
struct u16_Split
{
u8 Low;
u8 High;
operator u16()
{
return * cast( u16*, this );
}
};
ct inline
char char_binary( u8 value, u8 pos )
{
u8 mask = 1 << pos ;
return ( (1 << pos) & value) == mask ? '1' : '0';
}
inline
void str_binary( char* result, u8 value )
{
#if 0
result[0] = char_binary( value, 0);
result[1] = char_binary( value, 1);
result[2] = char_binary( value, 2);
result[3] = char_binary( value, 3);
result[4] = char_binary( value, 4);
result[5] = char_binary( value, 5);
result[6] = char_binary( value, 6);
result[7] = char_binary( value, 7);
#else
result[0] = char_binary( value, 7);
result[1] = char_binary( value, 6);
result[2] = char_binary( value, 5);
result[3] = char_binary( value, 4);
result[4] = char_binary( value, 3);
result[5] = char_binary( value, 2);
result[6] = char_binary( value, 1);
result[7] = char_binary( value, 0);
#endif
}
inline
void print_as_binary( u8* data, uw size, char const* byte_term )
{
char
binary_string[9];
binary_string[8] = '\0';
while ( size-- )
{
str_binary( binary_string, data[0]);
printf( "%s%s", binary_string, byte_term );
data += 1;
}
}
-29
View File
@@ -1,29 +0,0 @@
@echo off
if not exist build\nul (
meson setup build
)
echo:
if not exist tests\listing_0037_single_register_mov (
echo Assembling: listing_0037_single_register_mov.asm
call nasm ".\tests\listing_0037_single_register_mov.asm"
)
if not exist tests\listing_0038_many_register_mov (
echo Assembling: listing_0038_many_register_mov.asm
call nasm ".\tests\listing_0038_many_register_mov.asm"
)
if not exist tests\listing_0039_more_movs (
echo Assembling: listing_0039_more_movs.asm
call nasm ".\tests\listing_0039_more_movs.asm"
)
if not exist tests\listing_0040_challenge_movs (
echo Assembling: listing_0040_challenge_movs.asm
call nasm ".\tests\listing_0040_challenge_movs.asm"
)
echo:
ninja -C build
-22
View File
@@ -1,22 +0,0 @@
@echo off
if exist build\nul (
@RD /S /Q "build"
)
if exist tests\listing_0037_single_register_mov (
DEL /Q tests\listing_0037_single_register_mov
)
if exist tests\listing_0038_many_register_mov (
DEL /Q tests\listing_0038_many_register_mov
)
if exist tests\listing_0039_more_movs (
DEL /Q tests\listing_0039_more_movs
)
if exist tests\listing_0040_challenge_movs (
DEL /Q tests\listing_0040_challenge_movs
)
BIN
View File
Binary file not shown.
-13
View File
@@ -1,13 +0,0 @@
project( 'sim_8086', 'c', 'cpp', default_options : ['buildtype=debug'] )
include_thirdparty = include_directories( '../thirdparty' )
# add_global_arguments('-E', language : 'cpp')
if get_option('buildtype').startswith('debug')
add_project_arguments('-DBuild_Debug', language : 'cpp')
endif
executable( 'sim_8086', 'sim_8086.cpp', include_directories : include_thirdparty )
-756
View File
@@ -1,756 +0,0 @@
#include "bloat.hpp"
// Octal formatting is used heavily throughout
// See: https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781f2f3c0353da
// (x86 is an octal machine)
namespace Op
{
ct u8 Mask = 00210;
ct u8 Mask_Low = 0b11110000;
ct u8 Mask_High = 0b00001111;
ct u8 Mask_Imme = 0b00111000;
#define D_Opcodes \
D_Entry( mov_RM_R ) \
D_Entry( mov_Im_RM ) \
D_Entry( mov_Im_R ) \
D_Entry( mov_M_Acc ) \
D_Entry( mov_Acc_M ) \
D_Entry( mov_RM_SR ) \
D_Entry( mov_SR_RM ) \
enum Code : u8
{
mov_RM_R = 0b10001000,
mov_Im_RM = 0b11001100,
mov_Im_R = 0b10110000,
mov_M_Acc = 0b10100000,
mov_Acc_M = 0b10100010,
mov_RM_SR = 0b10001110,
mov_SR_RM = 0b10001100
};
char const* str( Code type )
{
switch ( type )
{
#define D_Entry( Entry_ ) \
case Entry_: \
return ZPL_STRINGIFY(Entry_); \
D_Opcodes
#undef D_Entry
}
return Msg_Invalid_Value;
}
char const* meumonic( Code type )
{
switch ( type )
{
case mov_RM_R :
case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "mov";
}
return Msg_Invalid_Value;
}
char const* intuitive( Code type )
{
switch ( type )
{
case mov_RM_R :
case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "move";
}
return Msg_Invalid_Value;
}
#undef D_Opcodes
}
namespace Field
{
inline
u8 offset_left_reg( u8 reg )
{
return reg << 3;
}
// https://i.imgur.com/drsyYnM.png
enum Direction : u8
{
Mask_Dir = 0b00000010,
Dir_Src = 0b00,
Dir_Dest = 0b10,
};
inline
char const* str_direction( Direction direction )
{
switch ( direction )
{
case Dir_Dest:
return "Destination";
case Dir_Src:
return "Source";
}
return Msg_Invalid_Value;
}
// https://i.imgur.com/9Op8Lnd.png
enum Width : u8
{
Mask_Width = 0b00000001,
Mask_Width_Imme = 0b00001000,
Width_Byte = 0b00,
Width_Word = 0b01,
};
inline
char const* str_width( Width width )
{
switch ( width )
{
case Width_Byte:
return "Byte";
case Width_Word:
return "Word";
}
return Msg_Invalid_Value;
}
// https://i.imgur.com/Job2oPd.png
enum Mode : u8
{
Mask_Mode = 0b11000000,
Mode_Mem = 0b00000000,
Mode_Mem8 = 0b01000000,
Mode_Mem16 = 0b10000000,
Mode_Reg = 0b11000000,
};
char const* str_mode( Mode mode )
{
switch (mode)
{
case Mode_Mem:
return "Memory: No Displacement";
case Mode_Mem8:
return "Memory: 8-bit Displacment";
case Mode_Mem16:
return "Memory: 16-bit Displacement";
case Mode_Reg:
return "Register";
}
return Msg_Invalid_Value;
}
ct u8 Mask_Memory = 0b00000111;
// https://i.imgur.com/Tm5roJu.png
enum Memory : u8
{
Add_BX_SI = 0b000,
Add_BX_DI = 0b001,
Add_BP_SI = 0b010,
Add_BP_DI = 0b011,
Add_SI = 0b100,
Add_DI = 0b101,
Add_Direct = 0b110,
Add_BX = 0b111,
Num_Memory
};
char const* str_memory( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"BX + SI",
"BX + DI",
"BP + SI",
"BP + DI",
"SI",
"DI",
"BP",
"BX"
};
return mem_to_str[ mem ];
}
char const* str_memory_intuitive( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"Base.16 + Stack.Index",
"Base.16 + Destination.Index",
"Stack.Base + Stack.Index",
"Stack.Base + Destination.Index",
"Stack.Index",
"Destination.Index",
"Stack.Base",
"BX"
};
return mem_to_str[ mem ];
}
}
namespace Register
{
ct u8 Mask_Imme = 0b00000111;
ct u8 Mask_Left = 0b00111000;
ct u8 Mask_Right = 0b00000111;
#define D_Opcodes \
D_Entry( AL ) \
D_Entry( CL ) \
D_Entry( DL ) \
D_Entry( BL ) \
D_Entry( AH ) \
D_Entry( CH ) \
D_Entry( DH ) \
D_Entry( BH ) \
D_Entry( AX ) \
D_Entry( CX ) \
D_Entry( DX ) \
D_Entry( BX ) \
D_Entry( SP ) \
D_Entry( BP ) \
D_Entry( SI ) \
D_Entry( DI ) \
enum Type : u8
{
AL = 0b000,
CL = 0b001,
DL = 0b010,
BL = 0b011,
AH = 0b100,
CH = 0b101,
DH = 0b110,
BH = 0b111,
AX = 0b000,
CX = 0b001,
DX = 0b010,
BX = 0b011,
SP = 0b100,
BP = 0b101,
SI = 0b110,
DI = 0b111,
Num = 16
};
char const* meumonic( Type type, u8 Width )
{
static char const*
Type_To_Meumonic[ Num ] =
{
#define D_Entry( Entry_ ) #Entry_,
D_Opcodes
#undef D_Entry
};
return Type_To_Meumonic[ type + Width * ( 7 + 1 ) ];
}
char const* intuitive( Type type, u8 Width )
{
static char const*
Type_To_Intuitive[ Num ] =
{
"Accumulator.Low",
"Count.Low",
"Data.Low",
"Base.Low",
"Accumulator.High",
"Count.High",
"Data.High",
"Base.High",
"Accumulator.16",
"Count.16",
"Data.16",
"Base.16",
"Stack.Pointer",
"Stack.Base",
"Source.Index",
"Destination.Index",
};
return Type_To_Intuitive[ type + Width * ( 7 + 1 ) ];
}
}
struct Octal
{
u8 Low : 3;
u8 High : 3;
u8 Dir : 1;
u8 Write : 1;
operator u8()
{
return * cast( u8*, this);
}
};
struct POD_Instruction
{
// 8086 Instructions are 1 to 6 bytes in length.
union
{
u8* Ptr;
u8 Byte[6];
Octal Instr;
struct
{
u8 Pad[2];
u16_Split Disp;
u16_Split Data;
}
EffAddr;
struct
{
u8 Pad[1];
u16_Split Data;
}
Imme;
struct
{
u8 Pad;
u16_Split Data;
}
Addr;
};
// If directly referencing blob data:
// Part of next instruction, do not use as stratch memory.
u16 Pad;
};
struct Instruction : public POD_Instruction
{
using Code = Op::Code;
using Direction = Field::Direction;
using Mode = Field::Mode;
using Memory = Field::Memory;
using Width = Field::Width;
using Reg = Register::Type;
inline
Direction get_direction()
{
Direction direction = cast(Direction, Byte[0] & Field::Mask_Dir);
return direction;
}
inline
Mode get_mode()
{
Mode mode = cast( Mode, Byte[1] & Field::Mask_Mode );
return mode;
}
inline
Code get_opcode( u8 mask )
{
Op::Code opcode = cast( Op::Code, Byte[0] & mask );
return opcode;
}
inline
Width get_width( u8 mask )
{
Width width = cast( Width, Byte[0] & mask );
return width;
}
inline
Reg mode_operand_left_reg()
{
u8
operand = Byte[1] & Register::Mask_Left;
operand >>= 3;
return cast(Reg, operand);
}
inline
Reg mode_operand_right_reg()
{
u8 operand = Byte[1] & Register::Mask_Right;
return cast( Reg, operand );
}
forceinline
void dissassemble_mode( char const*& str_operand, Width& width, u8& length )
{
using namespace Field;
using namespace Op;
using namespace Register;
switch ( get_mode() )
{
case Mode_Mem:
{
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
length += 2;
if ( operand_right == Add_Direct )
{
u16 address = EffAddr.Disp;
str_operand = string_format( "[ %u ]", address );
}
else
{
str_operand = str_memory( operand_right );
}
}
break;
case Mode_Mem8:
{
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
length += 1;
str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), EffAddr.Disp.Low );
}
break;
case Mode_Mem16:
{
length += 2;
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
u16 address = EffAddr.Disp;
str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), address );
}
break;
case Mode_Reg:
str_operand = Register::meumonic( mode_operand_right_reg(), width );
break;
}
}
u8 dissassemble( zpl_string* result_out )
{
using namespace Field;
using namespace Op;
using namespace Register;
u8 length = 1;
zpl_string assembly = string_make( 32);
Code code = get_opcode( Op::Mask );
Direction dir = get_direction();
char const* str_operand_left = nullptr;
char const* str_operand_right = nullptr;
const u8 code_low = Byte[0] & Op::Mask_Low;
const u8 code_high = Byte[0] & Op::Mask_High;
const u8 sig_imme = Byte[0] & Op::Mask_Imme;
if ( get_opcode( Op::Mask_Low ) == mov_Im_R )
{
Width width = get_width( Mask_Width_Imme );
Reg reg = cast(Reg, Byte[0] & Register::Mask_Right );
u16 immediate = width == Width_Byte ?
Imme.Data.Low : Imme.Data;
str_operand_left = Register::meumonic( reg, width );
str_operand_right = string_format( "%u", immediate );
}
else
{
switch ( code )
{
#pragma region mov
case mov_RM_R:
{
length++;
Width width = get_width( Mask_Width );
str_operand_left = Register::meumonic( mode_operand_left_reg(), width );
dissassemble_mode( str_operand_right, width, length );
}
break;
case mov_Im_RM:
{
Width width = get_width( Mask_Width_Imme );
Memory operand_left = cast( Memory, Byte[1] & Mask_Memory );
u16 address = EffAddr.Disp;
u16 immediate = width == Width_Byte ?
EffAddr.Data.Low : EffAddr.Data;
dissassemble_mode( str_operand_left, width, length );
str_operand_right = string_format( "%u", immediate );
}
break;
case mov_M_Acc:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
str_operand_right = string_format( "%u", address );
}
break;
case mov_Acc_M:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_right = string_format( "%u", address );
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
}
break;
case mov_RM_SR:
{
}
break;
case mov_SR_RM:
{
}
break;
#pragma endregion mov
}
}
assembly = string_format( assembly, 32, "\n%s %s, %s"
// opcode operand_right, operand_left
, Op::meumonic( code)
, str_operand_right
, str_operand_left
);
if ( result_out == nullptr )
return length;
if ( * result_out == nullptr )
* result_out = string_make( zpl_kilobytes(1) );
* result_out = string_append( * result_out, assembly );
zpl_printf("\n\nAssembly: %s\n\n", assembly);
return length;
}
};
namespace Tests
{
void try_mock_instruction()
{
using namespace Field;
using namespace Op;
using namespace Register;
Instruction
mock; // mov CX, BX
mock.Byte[0] = mov_RM_R | Dir_Src | Field::Width_Word;
mock.Byte[1] = Field::Mode_Reg | offset_left_reg(BX) | CX;
zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX");
print_nl();
print_as_binary( & mock.Byte[0], 1, " " );
print_as_binary( & mock.Byte[1], 1, " " );
print_nl();
zpl_string dissasembly = nullptr;
mock.dissassemble( & dissasembly);
}
void try_blob_single_move()
{
zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov");
zpl_file_contents
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0037_single_register_mov" );
if (blob.data == nullptr )
return;
u32 left = blob.size;
u8* data = cast( u8*, blob.data );
print_nl();
print_as_binary( data, left, " " );
print_nl();
zpl_string dissasembly = nullptr;
Instruction
instr;
instr.Byte[0] = data[0];
instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly);
}
void try_blob_many_moves()
{
zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov");
zpl_file_contents
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0038_many_register_mov" );
if (blob.data == nullptr )
return;
u32 left = blob.size;
u8* data = cast( u8*, blob.data );
print_nl();
print_as_binary( data, left, " " );
print_nl();
zpl_string dissasembly = string_make( "bits 16\n");
while ( left )
{
Instruction
instr;
instr.Byte[0] = data[0];
instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly);
data += 2;
left -= 2;
}
zpl_printf("\n\nDissassemlby:\n%s", dissasembly);
dissasembly = zpl_string_append_fmt( dissasembly, "\n" );
zpl_printf("\n\nSaving to file");
zpl_file_write_contents("tests/listing_0038_many_register_mov.out.asm"
, dissasembly
, zpl_string_length(dissasembly)
, nullptr
);
}
void try_blob_more_moves()
{
zpl_printf("\n\nAttempting to read blob: listing_0039_more_movs");
zpl_file_contents
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0039_more_movs" );
if (blob.data == nullptr )
return;
u32 left = blob.size;
u8* data = cast( u8*, blob.data );
print_nl();
print_as_binary( data, left, " " );
print_nl();
zpl_string dissasembly = string_make( "bits 16\n");
while ( left )
{
Instruction
instr;
instr.Ptr = data;
u8 length = instr.dissassemble( & dissasembly);
data += length;
left -= length;
}
zpl_printf("\n\nDissassemlby:\n%s", dissasembly);
dissasembly = zpl_string_append_fmt( dissasembly, "\n" );
zpl_printf("\n\nSaving to file");
zpl_file_write_contents("tests/listing_0039_more_movs.asm.out.asm"
, dissasembly
, zpl_string_length(dissasembly)
, nullptr
);
}
}
int main()
{
zpl_printf("sim 8086!");
setup();
f64 start = zpl_time_rel();
// Tests::try_blob_single_move();
// Tests::try_blob_many_moves();
Tests::try_blob_more_moves();
f64 end = zpl_time_rel();
f64 ms = (end - start) * 100;
printf("\n\nElapsed Time: %lf ms", ms);
printf("\n\n");
cleanup();
return 0;
}
@@ -1 +0,0 @@
@@ -1,19 +0,0 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ======================================================================== */
; ========================================================================
; LISTING 37
; ========================================================================
bits 16
mov cx, bx
@@ -1 +0,0 @@
‰Ùˆå‰Ú‰Þ‰ûˆÈˆí‰Ã‰ó‰ü‰Å
@@ -1,29 +0,0 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ======================================================================== */
; ========================================================================
; LISTING 38
; ========================================================================
bits 16
mov cx, bx
mov ch, ah
mov dx, bx
mov si, bx
mov bx, di
mov al, cl
mov ch, ch
mov bx, ax
mov bx, si
mov sp, di
mov bp, ax
@@ -1,13 +0,0 @@
bits 16
mov CX, BX
mov CH, AH
mov DX, BX
mov SI, BX
mov BX, DI
mov AL, CL
mov CH, CH
mov BX, AX
mov BX, SI
mov SP, DI
mov BP, AX
Binary file not shown.
-47
View File
@@ -1,47 +0,0 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 39
; ========================================================================
bits 16
; Register-to-register
mov si, bx
mov dh, al
; 8-bit immediate-to-register
mov cl, 12
mov ch, -12
; 16-bit immediate-to-register
mov cx, 12
mov cx, -12
mov dx, 3948
mov dx, -3948
; Source address calculation
mov al, [bx + si]
mov bx, [bp + di]
mov dx, [bp]
; Source address calculation plus 8-bit displacement
mov ah, [bx + si + 4]
; Source address calculation plus 16-bit displacement
mov al, [bx + si + 4999]
; Dest address calculation
mov [bx + di], cx
mov [bp + si], cl
mov [bp], ch
@@ -1,43 +0,0 @@
bits 16
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
Binary file not shown.
@@ -1,38 +0,0 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 40
; ========================================================================
bits 16
; Signed displacements
mov ax, [bx + di - 37]
mov [si - 300], cx
mov dx, [bx - 32]
; Explicit sizes
mov [bp + di], byte 7
mov [di + 901], word 347
; Direct address
mov bp, [5]
mov bx, [3458]
; Memory-to-accumulator test
mov ax, [2555]
mov ax, [16]
; Accumulator-to-memory test
mov [2554], ax
mov [15], ax
-58
View File
@@ -1,58 +0,0 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.*,</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate,</ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<ShowEmptyFolders>true</ShowEmptyFolders>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand>.\build.bat</BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand>.\clean.bat</CleanCommand>
<BuildWorkingDirectory>.\part_1</BuildWorkingDirectory>
<CancelBuild></CancelBuild>
<RunCommand>part_1/build/sim_8086.exe</RunCommand>
<DebugCommand>part_1/build/sim_8086.exe</DebugCommand>
<ExePathCommand>part_1/build/sim_8086.exe</ExePathCommand>
<DebugSln></DebugSln>
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
</Platforms>
<AdditionalIncludePaths>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\ATLMFC\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
</AdditionalIncludePaths>
<Defines></Defines>
<ConfigProperties>
<ConfigAndPlatform>
<Name>Debug:x64</Name>
<Defines></Defines>
<ForceIncludes></ForceIncludes>
</ConfigAndPlatform>
<Config>
<Name>Debug</Name>
<Defines></Defines>
</Config>
<Platform>
<Name>x64</Name>
<Defines></Defines>
</Platform>
</ConfigProperties>
<Children></Children>
</Workspace>
</N10X>
+9
View File
@@ -0,0 +1,9 @@
// raddbg 0.9.28 project file
target:
{
executable: "build/sim_8086.exe"
working_directory: ""
enabled: 1
label: "Sim 8086"
}
+421
View File
@@ -0,0 +1,421 @@
$path_root = split-path -Path $PSScriptRoot -Parent
$path_build = join-path $path_root 'build'
$path_code = join-path $path_root 'code'
$path_duffle = join-path $path_code 'duffle'
$path_8086 = join-path $path_code '8086'
$path_part_1 = join-path $path_code 'part_1'
$path_scripts = join-path $path_root 'scripts'
$path_toolchain = join-path $path_root 'toolchain'
if ((test-path $path_build) -eq $false) {
new-item -itemtype directory -path $path_build
}
# --- Toolchain Definition ---
# All tools default to LLVM/clang. The MIPS variables are kept for
# catalog parity with C:\projects\Pikuma\ps1\scripts\build_psyq.ps1,
# but are not used by the current Win32 build.
$compiler = "clang"
$linker = 'lld-link.exe'
$objcopy = 'llvm-objcopy'
$objdump = 'llvm-objdump'
$archiver = 'llvm-ar'
# --- Compiler Flags: General / Compilation Mode ---
$f_compile = '-c' # Compile to .o (no link)
$f_output = '-o' # Output path
$f_preprocess = '-E' # Preprocess to stdout
$f_syntax_only = '-fsyntax-only' # Parse + type-check, no codegen
$f_save_temps = '-save-temps' # Keep intermediate files
$f_show_includes = '-H' # Print include chain
$f_dependency_file = '-MF' # Write dep file (use with -MD)
$f_dependency_gen = '-MD' # Generate dep file alongside output
$f_emit_llvm = '-emit-llvm' # Emit LLVM IR
# --- Compiler Flags: Language Standard ---
$f_std_c11 = '-std=c11'
$f_std_c17 = '-std=c17'
$f_std_c23 = '-std=c23'
$f_std_gnu11 = '-std=gnu11'
$f_std_gnu17 = '-std=gnu17'
$f_std_gnu23 = '-std=gnu23'
$f_std_cpp17 = '-std=c++17'
$f_std_cpp20 = '-std=c++20'
$f_std_cpp23 = '-std=c++23'
$f_all_c = '-x','c' # Force C language
$f_all_cpp = '-x','c++' # Force C++ language
$f_all_asm = '-x','assembler' # Force asm
$f_all_asm_with_cpp = '-x','assembler-with-cpp'
# --- Compiler Flags: Preprocessor ---
$f_define = '-D' # #define NAME[=VALUE]
$f_undef = '-U' # #undef NAME
$f_include = '-I' # Add directory to search path
$f_include_system = '-isystem' # System header (suppresses warnings)
$f_include_quote = '-iquote' # Quote-only header path
$f_include_after = '-idirafter' # Append dir to search path
$f_include_file = '-include' # Force include file
$f_no_stdinc = '-nostdinc' # No standard include paths
$f_charset_utf8 = '-utf-8' # Source charset = UTF-8
# --- Compiler Flags: Warnings ---
# https://clang.llvm.org/docs/DiagnosticsReference.html
$f_wall = '-Wall'
$f_wextra = '-Wextra'
$f_werror = '-Werror'
$f_warnings_as_errors = '-Werror'
$f_wno_attributes = '-Wno-attributes'
$f_warnings_ignore = '-Wno-' # Prefix; usage: $f_warnings_ignore + 'unused'
$f_wno_unused_function = '-Wno-unused-function'
$f_wno_unused_variable = '-Wno-unused-variable'
$f_wno_switch = '-Wno-switch'
$f_wno_uninitialized = '-Wno-uninitialized'
$f_wno_implicit_function_declaration = '-Wno-implicit-function-declaration'
$f_wno_ms_include = '-Wno-microsoft-include'
$f_wno_return_type_c_linkage = '-Wno-return-type-c-linkage'
$f_wno_main_return_type = '-Wno-main-return-type'
$f_warning = '-W' # Prefix; usage: $f_warning + 'switch'
$f_pedantic = '-Wpedantic'
$f_doc_warnings = '-Wdocumentation'
# --- Compiler Flags: Optimization ---
$f_optimize_none = '-O0' # No optimization (debug default)
$f_optimize_debug = '-Og' # Optimize for debug
$f_optimize_size = '-Os' # Optimize for size
$f_optimize_fast = '-O2' # Optimize for speed (default release)
$f_optimize_max = '-O3' # Aggressive optimization
$f_optimize_intrinsics = '-Oi' # MSVC intrinsic hints (clang accepts; semantics ~ -O2)
$f_optimize_all = '-Ofast' # -O3 + non-IEEE-compliant math
$f_omit_frame_ptr = '-fomit-frame-pointer'
$f_no_omit_frame_ptr = '-fno-omit-frame-pointer'
$f_lto = '-flto' # Link-time optimization
$f_lto_thin = '-flto=thin'
# --- Compiler Flags: Debug / Profile ---
$f_debug = '-g' # Debug info (default DWARF)
$f_debug_codeview = '-gcodeview' # CodeView debug format (MS tools)
$f_debug_dwarf_4 = '-gdwarf-4' # Specific DWARF version
$f_debug_dwarf_5 = '-gdwarf-5'
$f_debug_line_tables_only = '-gline-tables-only'
$f_profiling_debug = '-fdebug-info-for-profiling'
$f_time_trace = '-ftime-trace' # Emit Chrome trace JSON
$f_coverage_generate = '-fprofile-instr-generate'
$f_coverage_use = '-fprofile-instr-use='
# --- Compiler Flags: Code Generation ---
$f_no_color_diagnostics = '-fno-color-diagnostics'
$f_color_diagnostics = '-fcolor-diagnostics'
$f_diagnostics_absolute = '-fdiagnostics-absolute-paths'
$f_exceptions_disabled = '-fno-exceptions'
$f_exceptions_enabled = '-fexceptions'
$f_RTTI_disabled = '-fno-rtti'
$f_RTTI_enabled = '-frtti'
$f_section_data = '-fdata-sections'
$f_section_functions = '-ffunction-sections'
$f_no_strict_alias = '-fno-strict-aliasing'
$f_strict_aliasing = '-fstrict-aliasing'
$f_signed_char = '-fsigned-char'
$f_unsigned_char = '-funsigned-char'
$f_pic = '-fPIC' # Position-independent code
$f_pie = '-fPIE' # Position-independent executable
$f_no_pic = '-fno-pic'
$f_no_pie = '-fno-pie'
$f_visible_hidden = '-fvisibility=hidden'
$f_visible_default = '-fvisibility=default'
$f_align_functions = '-falign-functions='
$f_align_loops = '-falign-loops='
$f_ms_extensions = '-fms-extensions' # Allow MSVC language extensions
$f_ms_compatibility = '-fms-compatibility'
$f_ms_runtime_lib_none = '-fno-ms-runtime'
$f_preprocess_non_integrated = '-no-integrated-cpp'
$f_stack_probes_disabled = '-mno-stack-arg-probe' # Requires the fully committed stack in link-modules
$f_stack_protector = '-fstack-protector'
$f_stack_protector_strong = '-fstack-protector-strong'
$f_stack_protector_all = '-fstack-protector-all'
$f_vptr = '-fvirtual-function-elimination'
$f_vectorize = '-vectorize-loops'
$f_vectorize_slp = '-vectorize-slp'
# --- Compiler Flags: Sanitizers ---
$f_sanitize_address = '-fsanitize=address'
$f_sanitize_undefined = '-fsanitize=undefined'
$f_sanitize_thread = '-fsanitize=thread'
$f_sanitize_memory = '-fsanitize=memory'
$f_sanitize_hwaddress = '-fsanitize=hwaddress'
$f_sanitize_address_safe = '-fsanitize=address,safe-stack'
$f_sanitize_cfi = '-fsanitize=cfi'
# --- Compiler Flags: Hardware Architecture ---
$f_arch_haswell = '-march=haswell'
# --- Compiler Flags: Environment / Target ---
$f_no_stdlib = '-nostdlib'
$f_freestanding = '-ffreestanding'
$f_no_builtin = '-fno-builtin'
$f_target_arch = '-target' # Usage: $f_target_arch + 'x86_64-pc-windows-msvc'
$f_target_abi = '-mabi='
$f_target_march = '-march='
$f_target_mtune = '-mtune='
$f_target_mcpu = '-mcpu='
$f_target_mfloat_abi = '-mfloat-abi='
$f_target_x86 = '-m64'
$f_target_x86_32 = '-m32'
$f_target_arm = '-marm'
$f_target_thumb = '-mthumb'
# --- Compiler Flags: Verbosity / Misc ---
$f_verbose = '-v'
$f_set_stack_size = '-stack=' # Stack size (linker-side, but accepted by clang)
$f_symbol_prefix = '-femit-all-decls'
# --- Linker Flags (passed via -Wl, to clang; or directly to gcc-style linkers) ---
# These are GNU ld-style flags. When invoking lld-link.exe directly, prefer
# the Win32-flavored flags below.
$f_linker = '-Wl,' # Prefix; usage: $f_linker + '--gc-sections'
$f_link_mapfile = '--Map=' # Output map file (GNU ld)
$f_link_gc_sections = '--gc-sections' # Dead-strip unused sections
$f_link_format = '--oformat=' # Output format (e.g. elf32-littlemips)
$f_link_start_group = '--start-group' # Circular library resolution
$f_link_end_group = '--end-group'
$f_link_static = '-static' # Static linking
$f_link_script = '-T' # Linker script
$f_link_lib_path = '-L' # Library search path
$f_link_lib = '-l' # Library shorthand (foo.lib -> -lfoo)
$f_link_relaxable = '--relax' # Enable linker relaxation
$f_link_strip_all = '-s' # Strip all symbols
$f_link_strip_debug = '-S' # Strip debug symbols
$f_link_no_undefined = '--no-undefined' # Error on unresolved symbols
$f_link_undefined = '-u' # Force a symbol to be defined
$f_link_version_script = '--version-script='
$f_link_entry = '-e' # Entry point (GNU ld)
$f_link_hash_style = '--hash-style='
$f_link_as_needed = '--as-needed'
$f_link_no_as_needed = '--no-as-needed'
# --- Linker Flags (Win32 lld-link, used directly) ---
# https://lld.llvm.org/windows_support.html
$f_nologo = '/NOLOGO'
$f_link_win_no_incremental = '/INCREMENTAL:NO'
$f_link_win_no_default_lib = '/NODEFAULTLIB'
$f_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
$f_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
$f_link_win_subsystem_efi_app = '/SUBSYSTEM:EFI_APPLICATION'
$f_link_win_subsystem_native = '/SUBSYSTEM:NATIVE'
$f_link_win_machine_32 = '/MACHINE:X86'
$f_link_win_machine_64 = '/MACHINE:X64'
$f_link_win_machine_arm = '/MACHINE:ARM'
$f_link_win_machine_arm64 = '/MACHINE:ARM64'
$f_link_win_debug = '/DEBUG'
$f_link_win_pdb = '/PDB:'
$f_link_win_path_output = '/OUT:'
$f_link_win_map = '/MAP:'
$f_link_win_entry = '/ENTRY:'
$f_link_win_lib_path = '/LIBPATH:'
$f_link_win_default_lib = '/DEFAULTLIB:'
$f_link_win_dll = '/DLL'
$f_link_win_optimize_ref = '/OPT:REF' # Eliminate unreferenced data/functions
$f_link_win_optimize_no_icf = '/OPT:NOICF' # Disable identical COMDAT folding
$f_link_win_optimize_no_ref = '/OPT:NOREF' # Disable dead-strip
$f_link_win_stack = '/STACK:'
$f_link_win_heap = '/HEAP:'
$f_link_win_merge = '/MERGE:'
$f_link_win_align = '/ALIGN:'
$f_link_win_base = '/BASE:'
$f_link_win_version = '/VERSION:'
$f_link_win_dynamic_base = '/DYNAMICBASE'
$f_link_win_release = '/RELEASE'
$f_link_win_force = '/FORCE'
$f_link_win_verbose = '/VERBOSE'
$f_link_win_wholearchive = '/WHOLEARCHIVE:'
$f_link_win_export = '/EXPORT:'
$f_link_win_delay_load = '/DELAYLOAD:'
$f_link_win_import = '/IMPORT:'
$f_link_win_def = '/DEF:'
$f_link_win_manifest = '/MANIFEST'
$f_link_win_manifest_no = '/MANIFEST:NO'
$f_link_win_manifest_uac = '/MANIFESTUAC:'
$f_link_win_manifest_input = '/MANIFESTINPUT:'
$f_link_win_section = '/SECTION:'
$f_link_win_swaprun = '/SWAPRUN'
$f_link_win_driver = '/DRIVER'
$f_link_win_large_address_aware = '/LARGEADDRESSAWARE'
$f_link_win_fail_if_mismatch = '/FAILIFMISMATCH'
$f_link_win_through = '/THREADOPT'
$f_link_win_error_report = '/ERRORREPORT'
$f_link_win_repro = '/BREPRO'
$f_link_win_safeseh = '/SAFESEH'
$f_link_win_guard_cf = '/GUARD:CF'
$f_link_win_guard_no_cf = '/GUARD:NOCF'
$f_link_win_pgo_run = '/USEPROFILE'
$f_link_win_pgo_gen = '/PROFILE'
$f_link_win_idl = '/IDLOUT:'
$f_link_win_delay_unload = '/DELAY:UNLOAD'
$f_link_win_compat_property = '/CETCOMPAT'
$f_link_win_debug_fastlink = '/DEBUG:FASTLINK'
$f_link_win_lib_list = '/LIB'
# --- Objcopy Flags ---
$f_objcopy_format = '-O' # Output format
$f_objcopy_add_section = '--add-section'
$f_objcopy_update_section = '--update-section'
$f_objcopy_set_section_flags = '--set-section-flags'
# --- Objdump Flags ---
$f_objdump_disassemble = '-d' # Disassemble all executable sections
$f_objdump_machine = '-M' # Usage: $f_objdump_machine + 'intel'
$f_objdump_source_lines = '-l' # Interleave source lines (requires -g)
$f_objdump_no_raw_insn = '--no-show-raw-insn' # Omit hex bytes
$f_objdump_reloc = '-r' # Inline relocations
$f_objdump_symbols = '--disassemble-symbols=' # Usage: $f_objdump_symbols + 'main'
$f_objdump_headers = '-x' # All headers + sections (verbose)
$f_objdump_section_contents = '-s' # Raw section contents (hex dump)
# --- Baseline Libraries (lld-link, Win32) ---
$libraries_win32 = @(
'kernel32.lib'
'user32.lib'
'gdi32.lib'
'vcruntime.lib'
)
# --- Functions ---
function compile-unit { param(
[string] $unit,
[string] $link_module,
[string[]] $include_paths,
[string[]] $user_compile_args
)
$compile_args = @()
$compile_args += $f_std_c11
$compile_args += $f_all_c
$compile_args += $f_arch_haswell
$compile_args += $f_ms_ex
$compile_args += $f_wall
$compile_args += $f_wno_attributes
$compile_args += $f_exceptions_disabled
$compile_args += $f_stack_probes_disabled
$compile_args += $f_diagnostics_absolute
$compile_args += $f_debug
foreach ($p in $include_paths) {
$compile_args += ($f_include + $p)
}
$compile_args += $user_compile_args
$compile_args += $f_compile
$compile_args += $unit
$compile_args += ($f_output + $link_module)
write-host "Compiling '$unit' -> '$link_module'" -ForegroundColor DarkCyan
$time_to_compile = Measure-Command { & $compiler $compile_args }
write-host "Compilation took $($time_to_compile.TotalMilliseconds)ms"
if ($LASTEXITCODE -ne 0) { write-error "Compilation failed for $unit. Aborting."; exit 1 }
}
function link-modules { param(
[string[]] $link_modules,
[string] $module,
[string] $pdb,
[string[]] $user_link_args
)
$base_name = [System.IO.Path]::GetFileNameWithoutExtension($module)
$map = join-path $path_build "$base_name.map"
$link_args = @()
$link_args += $f_nologo
$link_args += $f_link_win_no_default_lib
$link_args += $f_link_win_machine_64
$link_args += $f_link_win_no_incremental
$link_args += ($f_link_win_path_output + $module)
$link_args += $f_link_win_subsystem_console
$link_args += ($f_link_win_stack + '262144,262144') # 256 KiB reserved
$link_args += $f_link_win_debug
$link_args += ($f_link_win_entry + 'main')
$link_args += ($f_link_win_pdb + $pdb)
$link_args += ($f_link_win_map + $map)
foreach ($lib in $libraries_win32) {
$link_args += $lib
}
$link_args += $link_modules
$link_args += $user_link_args
write-host "Linking modules into '$module'" -ForegroundColor DarkCyan
$time_to_link = Measure-Command { & $linker $link_args }
write-host "Linking took $($time_to_link.TotalMilliseconds)ms"
if ($LASTEXITCODE -ne 0) { write-error "Linking failed. Aborting."; exit 1 }
}
function dump-disassembly { param([string] $obj, [string] $exe)
$base = [System.IO.Path]::GetFileNameWithoutExtension($exe)
$asm_obj = join-path $path_build "$base.obj.asm"
$asm_exe = join-path $path_build "$base.exe.asm"
$objdump_args = @()
$objdump_args += $f_objdump_disassemble
$objdump_args += ($f_objdump_machine + 'intel')
$objdump_args += $f_objdump_source_lines
$objdump_args += $f_objdump_no_raw_insn
write-host "Dumping object disassembly -> '$asm_obj'" -ForegroundColor DarkCyan
$time_to_objdump = Measure-Command { & $objdump $objdump_args $obj | Out-File -FilePath $asm_obj -Encoding utf8 }
write-host "Object disassembly took $($time_to_objdump.TotalMilliseconds)ms"
if ($LASTEXITCODE -ne 0) { write-error "objdump failed for $obj. Aborting."; exit 1 }
write-host "Dumping executable disassembly -> '$asm_exe'" -ForegroundColor DarkCyan
$time_to_objdump = Measure-Command { & $objdump $objdump_args $exe | Out-File -FilePath $asm_exe -Encoding utf8 }
write-host "Executable disassembly took $($time_to_objdump.TotalMilliseconds)ms"
if ($LASTEXITCODE -ne 0) { write-error "objdump failed for $exe. Aborting."; exit 1 }
}
function build-8086_decoder_table {
$includes = @(
$path_code
)
$source_c = join-path $path_8086 'decoder_table_generator.meta.c'
$module_c = join-path $path_build 'decoder_table_generator.meta.o'
$compile_args = @()
$compile_args += $f_debug
$compile_args += $f_optimize_none
# $compile_args += $f_optimize_size
$compile_args += ($f_define + 'BUILD_DEBUG=1')
compile-unit $source_c $module_c $includes $compile_args
$pdb = join-path $path_build 'decoder_table_generator.meta.pdb'
$exe = join-path $path_build 'decoder_table_generator.meta.exe'
link-modules $module_c $exe $pdb @()
dump-disassembly $module_c $exe
}
build-8086_decoder_table
function build-part_1 {
# The base lib uses subdir-prefixed includes (e.g. "duffle/dsl.h"),
# so the include root is <code>, not <code>/duffle.
$includes = @(
$path_code
)
$source_c = join-path $path_part_1 'sim_8086.c'
$module_c = join-path $path_build 'sim_8086.o'
$compile_args = @()
$compile_args += $f_debug
$compile_args += $f_optimize_none
# $compile_args += $f_optimize_size
$compile_args += ($f_define + 'BUILD_DEBUG=1')
compile-unit $source_c $module_c $includes $compile_args
$pdb = join-path $path_build 'sim_8086.pdb'
$exe = join-path $path_build 'sim_8086.exe'
link-modules $module_c $exe $pdb @()
dump-disassembly $module_c $exe
}
# build-part_1
+76
View File
@@ -0,0 +1,76 @@
function clone-gitrepo { param( [string] $path, [string] $url, [switch] $NoPull )
if (test-path $path) {
if ($NoPull) {
Write-Host "Skipping pull on $path (per -NoPull)."
return
}
# Already a checkout — refresh to upstream tip.
# --ff-only refuses to create a merge commit if the local branch has
# diverged, so a divergence surfaces as a clear git error instead of a
# silent merge. Preserves the read-only intent of update_deps.
Write-Host "Pulling latest into $path ..."
git -C $path pull --ff-only
}
else {
Write-Host "Cloning $url ..."
git clone --recursive $url $path
}
}
function Update-GitRepo
{
param( [string] $path, [string] $url, [string] $build_command )
if ( $build_command -eq $null ) {
write-host "Attempted to call Update-GitRepo without build_command specified"
return
}
$repo_name = $url.Split('/')[-1].Replace('.git', '')
$last_built_commit = join-path $path_build "last_built_commit_$repo_name.txt"
if ( -not(test-path -Path $path))
{
write-host "Cloining repo from $url to $path"
git clone $url $path
write-host "Building $url"
push-location $path
& "$build_command"
pop-location
git -C $path rev-parse HEAD | out-file $last_built_commit
$script:binaries_dirty = $true
write-host
return
}
git -C $path fetch
$latest_commit_hash = git -C $path rev-parse '@{u}'
$last_built_hash = if (Test-Path $last_built_commit) { Get-Content $last_built_commit } else { "" }
if ( $latest_commit_hash -eq $last_built_hash ) {
write-host
return
}
write-host "Build out of date for: $path, updating"
write-host 'Pulling...'
git -C $path pull
write-host "Building $url"
push-location $path
& $build_command
pop-location
$latest_commit_hash | out-file $last_built_commit
$script:binaries_dirty = $true
write-host
}
function verify-path { param( $path )
if (test-path $path) {return $true}
new-item -ItemType Directory -Path $path
return $false
}
+25
View File
@@ -0,0 +1,25 @@
# ════════════════════════════════════════════════════════════════════════════
# update_deps.ps1 — fetch / refresh.
# ════════════════════════════════════════════════════════════════════════════
param(
[switch] $NoPull # Skip the `git pull` step when the checkout already exists.
)
$path_root = split-path -Path $PSScriptRoot -Parent
$path_course_content = join-path $path_root 'course_content'
$misc = join-path $PSScriptRoot 'helpers/misc.ps1'; . $misc
# Halt on any error (instead of PowerShell's default `Continue`).
$ErrorActionPreference = 'Stop'
# --- Dependency Definition ---
# One external dep for now: Casey Muratori's computer_enhance course repo.
$url_computer_enhance = 'https://github.com/cmuratori/computer_enhance.git'
# --- Run ---
if ($NoPull) { clone-gitrepo $path_course_content $url_computer_enhance -NoPull }
else { clone-gitrepo $path_course_content $url_computer_enhance }
write-host ''
write-host 'Course content up to date.'
-100
View File
@@ -1,100 +0,0 @@
# Format Style Options - Created with Clang Power Tools
---
AccessModifierOffset: -4
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: Right
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AlignCompound: true
PadOperators: true
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
AlignConsecutiveMacros: AcrossComments
AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortLambdasOnASingleLine: None
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BeforeLambdaBody: false
BeforeWhile: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: true
BreakInheritanceList: BeforeColon
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
ColumnLimit: 180
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 4
ContinuationIndentWidth: 4
DeriveLineEnding: true
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseBlocks: true
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: false
IndentPPDirectives: None
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: true
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: After
SpaceBeforeCaseColon: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesInAngles: true
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: true
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: c++17
TabWidth: 4
UseTab: ForIndentation
...
-82
View File
@@ -1,82 +0,0 @@
<#
.DESCRIPTION
Helper script to format all header and source files in the repository.
By default, the script will recursively search under the repo root for
files to format. Users can give explicit parameters indicating how the
search should include and exclude filetypes.
If users don't want the search functionality, they can instead provide
an explicit list of files to format.
.PARAMETER RepoRoot
Full path to the root of the repository which is the target of the search.
Will default to the root of the current working directory.
.PARAMETER Include
Array of filetype extensions to target for formatting.
By default, targets standard extensions for header and source files.
Follows the same rules as the -Include parameter for Get-ChildItem.
.PARAMETER Exclude
Array of filetype extensions to exclude from formatting.
By default, excludes generated XAML files.
Follows the same rules as the -Exclude paramter for Get-ChildItem.
.PARAMETER Files
Array of files to format. The script will exit if one of the provided
filepaths does not exist.
.EXAMPLE
.\clang-format-all.ps1
Formats all header and source files under the repository root.
.EXAMPLE
.\clang-format-all.ps1 -RepoRoot 'S:\repos\calculator' -Include '*.h', '*.cpp' -Exclude '*.g.*'
Formats all *.h and *.cpp files under 'S:\repos\calculator', excluding files with an extension
like *.g.*
.EXAMPLE
.\clang-format-all.ps1 -File 'S:\repos\calculator\src\CalcViewModel\UnitConverterViewModel.h', 'S:\repos\calculator\src\CalcViewModel\MemoryItemViewModel.cpp'
Formats the specified files.
#>
[CmdletBinding( DefaultParameterSetName = 'Search' )]
param(
[Parameter( ParameterSetName = 'Search' )]
[ValidateScript({ Test-Path -PathType Container -Path $_ })]
[string] $RepoRoot = "$( (Get-Item .).FullName )/thirdparty",
[Parameter( ParameterSetName = 'Search' )]
[string[]] $Include = ( '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp' ),
[Parameter( ParameterSetName = 'Search' )]
[string[]] $Exclude = ( '*.g.*', "zpl.h" ),
[Parameter(
ParameterSetName = 'Explicit',
Mandatory)]
[ValidateScript({
$_ | Where-Object { -not (Test-Path -PathType Leaf -Path $_) } |
ForEach-Object { throw "Could not find file: [$_]" }
return $true
})]
[string[]] $Files
)
if ($PSCmdlet.ParameterSetName -eq 'Explicit')
{
# Use the file paths we were given.
$targetFiles = @($Files)
}
else
{
# Gather the files to be formatted.
$targetFiles = @(
Get-ChildItem -Recurse -Path $RepoRoot -Include $Include -Exclude $Exclude |
Select-Object -ExpandProperty FullName
)
}
# Format the files.
$formatParams = @(
'-i' # In-place
'-style=file' # Search for a .clang-format file in the parent directory of the source file.
'-verbose'
)
if ( $targetFiles )
{
clang-format $formatParams $targetFiles
}
-18369
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff