mirror of
https://github.com/Ed94/perfaware.git
synced 2026-09-17 21:23:48 +00:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
588fa20778 | ||
|
|
d3fd791537 | ||
|
|
6cca3fbe8b | ||
|
|
5e6e139cc0 | ||
|
|
b9b1ed460a | ||
|
|
749a712ceb | ||
|
|
7e533cbfb2 | ||
|
|
28e6e38c92 | ||
|
|
6a456097ba | ||
|
|
bfd02f4472 | ||
|
|
aa9c4d48f6 | ||
|
|
823ec3d499 | ||
|
|
77bda7741f | ||
|
|
8b4c8a2c71 | ||
|
|
6feff68b33 | ||
|
|
ac1fffa422 | ||
|
|
030876da48 | ||
|
|
8b3e6f5ef3 | ||
|
|
ce3206393a | ||
|
|
008d5e12b3 | ||
|
|
b09b51fdf5 | ||
|
|
154c85f253 | ||
|
|
f49fcbe510 | ||
|
|
31f81ec8e3 | ||
|
|
f116f02503 | ||
|
|
57154dc801 |
+34
-3
@@ -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
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
code/8086/* linguist-language=C
|
||||
code/duffle/* linguist-language=C
|
||||
code/part_1/* linguist-language=C
|
||||
@@ -0,0 +1,2 @@
|
||||
build
|
||||
course_content
|
||||
Vendored
+12
-7
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-19
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+2
-8
@@ -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
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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 )
|
||||
@@ -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```
|
||||
@@ -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!
|
||||

|
||||
@@ -0,0 +1,477 @@
|
||||
#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* 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* plan;
|
||||
|
||||
U1 opcode;
|
||||
U1 post_opcode;
|
||||
U1 mod_rm;
|
||||
|
||||
X8616_Direction d;
|
||||
X8616_Width w;
|
||||
X8616_Sign s;
|
||||
X8616_VariableShift v;
|
||||
X8616_Repeat z;
|
||||
X8616_DecodedReg reg_opcode;
|
||||
X8616_Segment sr_opcode;
|
||||
|
||||
X8616_Mod mod;
|
||||
X8616_DecodedReg reg;
|
||||
X8616_EA rm;
|
||||
X8616_Segment 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 X8616_OpcodePrefix
|
||||
x8616_decode_opcode(X8616_DecodePlan const* plan, U1 opcode)
|
||||
{
|
||||
U1 field_mask = 0;
|
||||
if (plan->flags & x8616_plan_has_d) field_mask |= u1_(1u << plan->d_shift);
|
||||
if (plan->flags & x8616_plan_has_w) field_mask |= u1_(1u << plan->w_shift);
|
||||
if (plan->flags & x8616_plan_has_s) field_mask |= u1_(1u << plan->s_shift);
|
||||
if (plan->flags & x8616_plan_has_v) field_mask |= u1_(1u << plan->v_shift);
|
||||
if (plan->flags & x8616_plan_has_z) field_mask |= u1_(1u << plan->z_shift);
|
||||
if (plan->flags & x8616_plan_has_reg) field_mask |= u1_(0b111u << plan->reg_shift);
|
||||
if (plan->flags & x8616_plan_has_sr) field_mask |= u1_(0b11u << plan->sr_shift);
|
||||
if (field_mask == 0) return 0;
|
||||
U1 stem_mask = u1_(~field_mask);
|
||||
if (stem_mask == 0) return 0;
|
||||
return C_(X8616_OpcodePrefix, (opcode & stem_mask) >> count_trailing_zeros_u4(stem_mask));
|
||||
}
|
||||
|
||||
internal void
|
||||
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 = C_(X8616_Repeat, (opcode >> plan->z_shift) & 0b1);
|
||||
}
|
||||
if (plan->prefix_kind == x8616_prefix_segment) {
|
||||
plex->prefixes.has_segment = 1;
|
||||
plex->prefixes.segment = C_(X8616_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_R 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.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 = C_(X8616_Direction, (plex->opcode >> plan->d_shift) & 0b1);
|
||||
plex->w = C_(X8616_Width, (plex->opcode >> plan->w_shift) & 0b1);
|
||||
plex->s = C_(X8616_Sign, (plex->opcode >> plan->s_shift) & 0b1);
|
||||
plex->v = C_(X8616_VariableShift, (plex->opcode >> plan->v_shift) & 0b1);
|
||||
plex->z = C_(X8616_Repeat, (plex->opcode >> plan->z_shift) & 0b1);
|
||||
plex->reg_opcode.r16 = C_(X8616_Reg16, (plex->opcode >> plan->reg_shift) & 0b111);
|
||||
plex->sr_opcode = C_(X8616_Segment, (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 = C_(X8616_Mod, x8616_modrm_mod(plex->mod_rm));
|
||||
plex->reg.r16 = C_(X8616_Reg16, x8616_modrm_reg(plex->mod_rm));
|
||||
plex->rm = C_(X8616_EA, x8616_modrm_rm(plex->mod_rm));
|
||||
plex->sr_modrm = C_(X8616_Segment, 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[(u1_(plex->mod) << 3) | u1_(plex->rm)];
|
||||
|
||||
plex->direct_memory = (plan->flags & x8616_plan_uses_rm) && plex->mod == x8616_mod_mem && plex->rm == x8616_ea_direct;
|
||||
|
||||
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.r16 = x8616_ax;
|
||||
|
||||
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.r16 = 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.r16 = C_(X8616_Reg16, 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.r8 = 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) & u1_(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 = x8616_decode_opcode(plan, plex->opcode);
|
||||
plex->instruction.d = (plan->flags & x8616_plan_has_d) ? plex->d : x8616_d_rm_dst;
|
||||
plex->instruction.w = (plan->flags & x8616_plan_has_w) ? plex->w : x8616_w_byte;
|
||||
plex->instruction.has_mod_rm = (plan->flags & x8616_plan_has_modrm) != 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#define x8616_decode_(...) x8616_decode((X8616_DecodeRequest){__VA_ARGS__})
|
||||
X8616_DecodeInfo x8616_decode(X8616_DecodeRequest request)
|
||||
{
|
||||
X8616_DecodeInfo result = {0};
|
||||
result.instruction_cap = request.instruction_cap;
|
||||
|
||||
while (result.source_consumed < request.source_len && result.instruction_count < request.instruction_cap) {
|
||||
X8616_DecodePlex plex = {0};
|
||||
plex.source = request.source + result.source_consumed;
|
||||
plex.source_size = request.source_len - 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.out_instructions[result.instruction_count] = plex.instruction;
|
||||
result.instruction_count += 1;
|
||||
if (consumed == false) consumed = 1;
|
||||
result.source_consumed += consumed;
|
||||
}
|
||||
|
||||
if (result.source_consumed < request.source_len && result.instruction_count == request.instruction_cap) {
|
||||
x8616_info_push(request.info_arena, & result.msgs, x8616_info_warning
|
||||
, x8616_info_output_full
|
||||
, result.source_consumed
|
||||
, 0
|
||||
, request.instruction_cap
|
||||
, 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;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
#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) {
|
||||
Bit_(x8616_decoded_operand_none, 0),
|
||||
Bit_(x8616_decoded_operand_register, 1),
|
||||
Bit_(x8616_decoded_operand_segment, 2),
|
||||
Bit_(x8616_decoded_operand_memory, 3),
|
||||
Bit_(x8616_decoded_operand_immediate, 4),
|
||||
Bit_(x8616_decoded_operand_relative, 5),
|
||||
Bit_(x8616_decoded_operand_far_ptr, 6),
|
||||
Bit_(x8616_decoded_operand_direct, 7),
|
||||
Bit_(x8616_decoded_operand_sign_extended, 8),
|
||||
Bit_(x8616_decoded_operand_implicit, 9),
|
||||
};
|
||||
|
||||
typedef Union_(X8616_DecodedReg) {
|
||||
X8616_Reg8 r8;
|
||||
X8616_Reg16 r16;
|
||||
};
|
||||
|
||||
typedef Struct_(X8616_DecodedOperand) {
|
||||
X8616_DecodedOperandFlags flags;
|
||||
X8616_WidthMode width;
|
||||
X8616_DecodedReg reg;
|
||||
X8616_Segment segment;
|
||||
X8616_Mod mod;
|
||||
X8616_EA 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;
|
||||
X8616_OpcodePrefix opcode;
|
||||
X8616_Direction d;
|
||||
X8616_Width w;
|
||||
B1 has_mod_rm;
|
||||
U1 size;
|
||||
U1 size_required;
|
||||
};
|
||||
|
||||
typedef Enum_(U2, X8616_DecodePlanFlags) {
|
||||
Bit_(x8616_plan_none, 0),
|
||||
Bit_(x8616_plan_has_modrm, 1),
|
||||
Bit_(x8616_plan_has_post_opcode, 2),
|
||||
Bit_(x8616_plan_has_d, 3),
|
||||
Bit_(x8616_plan_has_w, 4),
|
||||
Bit_(x8616_plan_has_s, 5),
|
||||
Bit_(x8616_plan_has_v, 6),
|
||||
Bit_(x8616_plan_has_z, 7),
|
||||
Bit_(x8616_plan_has_reg, 8),
|
||||
Bit_(x8616_plan_has_sr, 9),
|
||||
Bit_(x8616_plan_uses_rm, 10),
|
||||
Bit_(x8616_plan_is_prefix, 11),
|
||||
};
|
||||
|
||||
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* source;
|
||||
X8616_DecodedInstruction* out_instructions;
|
||||
U4 source_len;
|
||||
U4 instruction_cap;
|
||||
FArena* info_arena;
|
||||
};
|
||||
|
||||
typedef Struct_(X8616_DecodeInfo) {
|
||||
X8616_InfoList msgs;
|
||||
U4 source_consumed;
|
||||
U4 instruction_count;
|
||||
U4 instruction_cap;
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,486 @@
|
||||
#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_R encoding, U4 encoding_idx, X8616_InfoList_R 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_R encoding, U1 opcode) {
|
||||
return (opcode & encoding->opcode.mask) == encoding->opcode.bits;
|
||||
}
|
||||
|
||||
FI_ B4 x8616_decode_gen_plan_matches_second(X8616_DecodePlan_R plan, U1 byte) {
|
||||
if (plan->mod_rm.mask && ((byte & plan->mod_rm.mask) != plan->mod_rm.bits)) return false;
|
||||
if (plan->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_R 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_R encoding = x8616_encodings + encoding_idx;
|
||||
if (x8616_decode_gen_encoding_matches_opcode(encoding, C_(U1, opcode)) == false) continue;
|
||||
|
||||
X8616_DecodePlan_R 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 str8gen_append_u4(Str8Gen_R out, U4 value, U4 radix, U4 min_digits) {
|
||||
UTF8 buffer[64]; Info_str8_from_u4 info = str8_from_u4_info(value, radix, min_digits, 0);
|
||||
Str8 text = str8_from_u4_buf(slice_ut_arr(buffer), value, radix, min_digits, 0, info);
|
||||
str8gen_append_str8(out, text);
|
||||
}
|
||||
|
||||
I_ void str8gen_append_hex_u1(Str8Gen_R out, U1 value) { str8gen_append_u4(out, value, 16, 2); }
|
||||
I_ void str8gen_append_hex_u2(Str8Gen_R out, U2 value) { str8gen_append_u4(out, value, 16, 4); }
|
||||
I_ void str8gen_append_dec (Str8Gen_R out, U4 value) { str8gen_append_u4(out, value, 10, 1); }
|
||||
|
||||
FI_ Slice scratch_push(U8 len) { return fstack_push_(smem.scratch, len); }
|
||||
|
||||
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__))
|
||||
|
||||
#define dec(v) str8_from_u4(v, .radix = 10, .min_digits = 1)
|
||||
#define hex_u1(v) str8_from_u4(v, .radix = 16, .min_digits = 2)
|
||||
#define hex_u2(v) str8_from_u4(v, .radix = 16, .min_digits = 4)
|
||||
#define entry(k,v) { ktl_str8_key(k), v }
|
||||
|
||||
internal void
|
||||
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[] = {
|
||||
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)),
|
||||
};
|
||||
str8gen_append_fmt(out, template, ktl_str8_from_arr(tbl));
|
||||
}}
|
||||
|
||||
#define gen_fmt(out, tmpl, ...) str8gen_append_fmt((out), (tmpl), ktl_str8_from_arr(((KTL_Slot_Str8[]){ __VA_ARGS__ })))
|
||||
|
||||
internal Str8
|
||||
x8616_decode_gen_emit(Str8Gen_R out, X8616_DecodeGen_R gen)
|
||||
{
|
||||
#pragma push_macro("RO_")
|
||||
#pragma push_macro("global")
|
||||
#undef RO_
|
||||
#undef global
|
||||
defer_rewind(smem.scratch.top)
|
||||
{
|
||||
str8gen_append_str8(out, slit8(
|
||||
"// Generated from encoder_table.h. Do not hand-edit.\n"
|
||||
"// Plan 0 is a nil/invalid entry.\n"
|
||||
"#ifdef INTELLISENSE_DIRECTIVES\n"
|
||||
"#\tinclude \"dsl.h\"\n"
|
||||
"#endif\n\n"
|
||||
));
|
||||
gen_fmt(out, code_str8(RO_ global X8616_DecodePlan x8616_decode_plans[<plan_count>] =\n{\n)
|
||||
, entry("plan_count", dec(X8616_ENCODING_COUNT + 1))
|
||||
);
|
||||
|
||||
for (U4 idx = 0; idx < X8616_ENCODING_COUNT + 1; ++ idx) { x8616_decode_gen_emit_plan(out, gen->plans + idx); }
|
||||
|
||||
str8gen_append_str8(out, code_str8(
|
||||
};\n\n
|
||||
));
|
||||
|
||||
str8gen_append_str8(out, code_str8(RO_ global U2 x8616_decode_dispatch[256] =\n{\n));
|
||||
{
|
||||
Str8 line = code_str8(\t<e0>, <e1>, <e2>, <e3>, <e4>, <e5>, <e6>, <e7>, <e8>, <e9>, <e10>, <e11>, <e12>, <e13>, <e14>, <e15>,\n);
|
||||
for (U4 idx = 0; idx < 256; idx += 16) defer_rewind(smem.scratch.top) {
|
||||
U2_R d = gen->dispatch + idx;
|
||||
gen_fmt(out, line,
|
||||
entry("e0", hex_u2(d[0])),
|
||||
entry("e1", hex_u2(d[1])),
|
||||
entry("e2", hex_u2(d[2])),
|
||||
entry("e3", hex_u2(d[3])),
|
||||
entry("e4", hex_u2(d[4])),
|
||||
entry("e5", hex_u2(d[5])),
|
||||
entry("e6", hex_u2(d[6])),
|
||||
entry("e7", hex_u2(d[7])),
|
||||
entry("e8", hex_u2(d[8])),
|
||||
entry("e9", hex_u2(d[9])),
|
||||
entry("e10", hex_u2(d[10])),
|
||||
entry("e11", hex_u2(d[11])),
|
||||
entry("e12", hex_u2(d[12])),
|
||||
entry("e13", hex_u2(d[13])),
|
||||
entry("e14", hex_u2(d[14])),
|
||||
entry("e15", hex_u2(d[15]))
|
||||
);
|
||||
}
|
||||
}
|
||||
str8gen_append_str8(out, code_str8(};\n\n));
|
||||
|
||||
gen_fmt(out, code_str8(RO_ global U1 x8616_decode_aux[<aux_count>] =\n{\n)
|
||||
, entry("aux_count", dec(gen->aux_count))
|
||||
);
|
||||
{
|
||||
Str8 line = code_str8(\t<a0>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6>, <a7>, <a8>, <a9>, <a10>, <a11>, <a12>, <a13>, <a14>, <a15>,\n);
|
||||
U4 idx = 0;
|
||||
for (; idx + 16 <= gen->aux_count; idx += 16) defer_rewind(smem.scratch.top) {
|
||||
U1_R a = gen->aux + idx;
|
||||
gen_fmt(out, line,
|
||||
entry("a0", hex_u1(a[0])),
|
||||
entry("a1", hex_u1(a[1])),
|
||||
entry("a2", hex_u1(a[2])),
|
||||
entry("a3", hex_u1(a[3])),
|
||||
entry("a4", hex_u1(a[4])),
|
||||
entry("a5", hex_u1(a[5])),
|
||||
entry("a6", hex_u1(a[6])),
|
||||
entry("a7", hex_u1(a[7])),
|
||||
entry("a8", hex_u1(a[8])),
|
||||
entry("a9", hex_u1(a[9])),
|
||||
entry("a10", hex_u1(a[10])),
|
||||
entry("a11", hex_u1(a[11])),
|
||||
entry("a12", hex_u1(a[12])),
|
||||
entry("a13", hex_u1(a[13])),
|
||||
entry("a14", hex_u1(a[14])),
|
||||
entry("a15", hex_u1(a[15]))
|
||||
);
|
||||
}
|
||||
if (idx < gen->aux_count) {
|
||||
str8gen_append_str8(out, slit8("\t"));
|
||||
for (; idx < gen->aux_count; ++ idx) {
|
||||
str8gen_append_hex_u1(out, gen->aux[idx]); str8gen_append_str8(out, slit8(", "));
|
||||
}
|
||||
str8gen_append_str8(out, slit8("\n"));
|
||||
}
|
||||
}
|
||||
str8gen_append_str8(out, code_str8(};\n\n));
|
||||
|
||||
gen_fmt(out, code_str8(enum {\n
|
||||
\tX8616_DECODE_PLAN_COUNT = <plan_count>,\n
|
||||
\tX8616_DECODE_AUX_COUNT = <aux_count>,
|
||||
\n};\n
|
||||
),
|
||||
entry("plan_count", dec(X8616_ENCODING_COUNT + 1)),
|
||||
entry("aux_count", dec(gen->aux_count))
|
||||
);
|
||||
}
|
||||
return str8(out->ptr, out->len);
|
||||
#pragma pop_macro("RO_")
|
||||
#pragma pop_macro("global")
|
||||
}
|
||||
|
||||
#undef gen_fmt
|
||||
#undef entry
|
||||
#undef hex_u2
|
||||
#undef hex_u1
|
||||
#undef dec
|
||||
|
||||
int 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;
|
||||
}
|
||||
@@ -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
@@ -0,0 +1,362 @@
|
||||
// Generated from encoder_table.h. Do not hand-edit.
|
||||
// Plan 0 is a nil/invalid entry.
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# include "dsl.h"
|
||||
#endif
|
||||
|
||||
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}, },
|
||||
{ 0x041a, 0x02, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x02, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0110, 0x02, 0x00, 0x00, {0x03, 0x07}, 2, 1, 0, 0, 3, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0018, 0x02, 0x00, 0x00, {0x06, 0x0a}, 2, 4, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x040a, 0x02, 0x00, 0x02, {0x01, 0x04}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x20}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x0b, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0100, 0x0b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0200, 0x0b, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x0c, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0100, 0x0c, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0200, 0x0c, 0x00, 0x02, {0x05, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x0d, 0x00, 0x00, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0100, 0x0d, 0x00, 0x02, {0x06, 0x03}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x0e, 0x00, 0x00, {0x06, 0x08}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x0e, 0x00, 0x00, {0x06, 0x0e}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x0f, 0x00, 0x00, {0x08, 0x06}, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x0f, 0x00, 0x00, {0x0e, 0x06}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x10, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x11, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x12, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x13, 0x00, 0x02, {0x02, 0x01}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x14, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 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}, },
|
||||
{ 0x041a, 0x03, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0432, 0x03, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x03, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x04, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x04, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x04, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x05, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0432, 0x05, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x05, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x06, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0432, 0x06, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x06, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x07, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x07, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x07, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x08, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0432, 0x08, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x08, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x09, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x09, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x09, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x041a, 0x0a, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0432, 0x0a, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x0a, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x18, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0100, 0x18, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x19, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x1a, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x1b, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0100, 0x1b, 0x00, 0x02, {0x03, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x1c, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x1f, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x20, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x22, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x30, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x23, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x27, 0x00, 0x00, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x1d, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x1e, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0004, 0x21, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, },
|
||||
{ 0x0004, 0x24, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x0a, 0xff}, },
|
||||
{ 0x0000, 0x25, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x26, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x2b, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x2c, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x08, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x2d, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x2e, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x28, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x29, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0452, 0x2a, 0x00, 0x00, {0x01, 0x0f}, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, {0x38, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x2f, 0x00, 0x00, {0x01, 0x02}, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0412, 0x2f, 0x00, 0x00, {0x01, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x2f, 0x00, 0x00, {0x06, 0x07}, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0880, 0x30, 0x02, 0x00, {0x00, 0x00}, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x31, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x32, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x33, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x34, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0010, 0x35, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0800, 0x5b, 0x02, 0x00, {0x00, 0x00}, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0a00, 0x5c, 0x02, 0x00, {0x00, 0x00}, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x36, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x36, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x10, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x36, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x36, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x18, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x37, 0x00, 0x00, {0x0c, 0x00}, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x37, 0x00, 0x00, {0x0b, 0x00}, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x37, 0x00, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x20, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x37, 0x01, 0x00, {0x0d, 0x00}, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0402, 0x37, 0x01, 0x02, {0x01, 0x00}, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x28, 0x38}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x38, 0x00, 0x00, {0x00, 0x00}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0x00, 0x00}, {0x00, 0x00}, },
|
||||
{ 0x0000, 0x38, 0x00, 0x00, {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,
|
||||
};
|
||||
@@ -0,0 +1,109 @@
|
||||
#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_serialize_bad_request = 0x0B,
|
||||
x8616_info_serialize_invalid_record = 0x0C,
|
||||
x8616_info_serialize_unsupported_form = 0x0D,
|
||||
x8616_info_serialize_output_full = 0x0E,
|
||||
|
||||
x8616_info_count,
|
||||
};
|
||||
|
||||
/* 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;
|
||||
U2 source_size;
|
||||
U4 source_offset;
|
||||
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>."),
|
||||
[x8616_info_serialize_bad_request] = slit8("Serialize request is missing instructions, output, scratch, or info arena."),
|
||||
[x8616_info_serialize_invalid_record] = slit8("Serialize record <offset> is not printable (op <actual>)."),
|
||||
[x8616_info_serialize_unsupported_form] = slit8("Serialize record <offset> has an unsupported display form (op <actual>)."),
|
||||
[x8616_info_serialize_output_full] = slit8("Serialize output is full at record <offset>: capacity <expected>, produced <actual>."),
|
||||
};
|
||||
|
||||
typedef Struct_(X8616_InfoList) {
|
||||
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 msgs
|
||||
, X8616_InfoKind kind
|
||||
, X8616_InfoCode code
|
||||
, U4 source_offset
|
||||
, U2 source_size
|
||||
, U4 expected
|
||||
, U4 actual
|
||||
){
|
||||
assert(scratch != nullptr);
|
||||
msgs->count += 1;
|
||||
msgs->error_count += kind == x8616_info_error;
|
||||
msgs->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) { ++ msgs->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(msgs->first, msgs->last, msg, next);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "duffle/tables.h"
|
||||
# include "duffle/text.h"
|
||||
# include "info.h"
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# include "serializer.h"
|
||||
#endif
|
||||
|
||||
RO_ global Str8 x8616_serialize_header = slit8("bits 16\n\n");
|
||||
|
||||
RO_ global Str8 x8616_serialize_mnemonic[] = {
|
||||
[x8616_op_invalid] = slit8(""),
|
||||
[x8616_op_nop] = slit8("nop"),
|
||||
[x8616_op_mov] = slit8("mov"),
|
||||
[x8616_op_add] = slit8("add"),
|
||||
[x8616_op_or] = slit8("or"),
|
||||
[x8616_op_adc] = slit8("adc"),
|
||||
[x8616_op_sbb] = slit8("sbb"),
|
||||
[x8616_op_and] = slit8("and"),
|
||||
[x8616_op_sub] = slit8("sub"),
|
||||
[x8616_op_xor] = slit8("xor"),
|
||||
[x8616_op_cmp] = slit8("cmp"),
|
||||
[x8616_op_push] = slit8("push"),
|
||||
[x8616_op_pop] = slit8("pop"),
|
||||
[x8616_op_xchg] = slit8("xchg"),
|
||||
[x8616_op_in] = slit8("in"),
|
||||
[x8616_op_out] = slit8("out"),
|
||||
[x8616_op_xlat] = slit8("xlat"),
|
||||
[x8616_op_lea] = slit8("lea"),
|
||||
[x8616_op_lds] = slit8("lds"),
|
||||
[x8616_op_les] = slit8("les"),
|
||||
[x8616_op_lahf] = slit8("lahf"),
|
||||
[x8616_op_sahf] = slit8("sahf"),
|
||||
[x8616_op_pushf] = slit8("pushf"),
|
||||
[x8616_op_popf] = slit8("popf"),
|
||||
[x8616_op_inc] = slit8("inc"),
|
||||
[x8616_op_aaa] = slit8("aaa"),
|
||||
[x8616_op_daa] = slit8("daa"),
|
||||
[x8616_op_dec] = slit8("dec"),
|
||||
[x8616_op_neg] = slit8("neg"),
|
||||
[x8616_op_aas] = slit8("aas"),
|
||||
[x8616_op_das] = slit8("das"),
|
||||
[x8616_op_mul] = slit8("mul"),
|
||||
[x8616_op_imul] = slit8("imul"),
|
||||
[x8616_op_aam] = slit8("aam"),
|
||||
[x8616_op_div] = slit8("div"),
|
||||
[x8616_op_idiv] = slit8("idiv"),
|
||||
[x8616_op_aad] = slit8("aad"),
|
||||
[x8616_op_cbw] = slit8("cbw"),
|
||||
[x8616_op_cwd] = slit8("cwd"),
|
||||
[x8616_op_not] = slit8("not"),
|
||||
[x8616_op_shl] = slit8("shl"),
|
||||
[x8616_op_shr] = slit8("shr"),
|
||||
[x8616_op_sar] = slit8("sar"),
|
||||
[x8616_op_rol] = slit8("rol"),
|
||||
[x8616_op_ror] = slit8("ror"),
|
||||
[x8616_op_rcl] = slit8("rcl"),
|
||||
[x8616_op_rcr] = slit8("rcr"),
|
||||
[x8616_op_test] = slit8("test"),
|
||||
[x8616_op_rep] = slit8(""),
|
||||
[x8616_op_movs] = slit8("movs"),
|
||||
[x8616_op_cmps] = slit8("cmps"),
|
||||
[x8616_op_scas] = slit8("scas"),
|
||||
[x8616_op_lods] = slit8("lods"),
|
||||
[x8616_op_stos] = slit8("stos"),
|
||||
[x8616_op_call] = slit8("call"),
|
||||
[x8616_op_jmp] = slit8("jmp"),
|
||||
[x8616_op_ret] = slit8("ret"),
|
||||
[x8616_op_retf] = slit8("retf"),
|
||||
[x8616_op_je] = slit8("je"),
|
||||
[x8616_op_jl] = slit8("jl"),
|
||||
[x8616_op_jle] = slit8("jle"),
|
||||
[x8616_op_jb] = slit8("jb"),
|
||||
[x8616_op_jbe] = slit8("jbe"),
|
||||
[x8616_op_jp] = slit8("jp"),
|
||||
[x8616_op_jo] = slit8("jo"),
|
||||
[x8616_op_js] = slit8("js"),
|
||||
[x8616_op_jne] = slit8("jne"),
|
||||
[x8616_op_jnl] = slit8("jnl"),
|
||||
[x8616_op_jg] = slit8("jg"),
|
||||
[x8616_op_jnb] = slit8("jnb"),
|
||||
[x8616_op_ja] = slit8("ja"),
|
||||
[x8616_op_jnp] = slit8("jnp"),
|
||||
[x8616_op_jno] = slit8("jno"),
|
||||
[x8616_op_jns] = slit8("jns"),
|
||||
[x8616_op_loop] = slit8("loop"),
|
||||
[x8616_op_loopz] = slit8("loopz"),
|
||||
[x8616_op_loopnz] = slit8("loopnz"),
|
||||
[x8616_op_jcxz] = slit8("jcxz"),
|
||||
[x8616_op_int] = slit8("int"),
|
||||
[x8616_op_int3] = slit8("int3"),
|
||||
[x8616_op_into] = slit8("into"),
|
||||
[x8616_op_iret] = slit8("iret"),
|
||||
[x8616_op_clc] = slit8("clc"),
|
||||
[x8616_op_cmc] = slit8("cmc"),
|
||||
[x8616_op_stc] = slit8("stc"),
|
||||
[x8616_op_cld] = slit8("cld"),
|
||||
[x8616_op_std] = slit8("std"),
|
||||
[x8616_op_cli] = slit8("cli"),
|
||||
[x8616_op_sti] = slit8("sti"),
|
||||
[x8616_op_hlt] = slit8("hlt"),
|
||||
[x8616_op_wait] = slit8("wait"),
|
||||
[x8616_op_lock] = slit8(""),
|
||||
[x8616_op_segment] = slit8(""),
|
||||
};
|
||||
|
||||
RO_ global Str8 x8616_serialize_reg8[] = {
|
||||
[x8616_al] = slit8("al"),
|
||||
[x8616_cl] = slit8("cl"),
|
||||
[x8616_dl] = slit8("dl"),
|
||||
[x8616_bl] = slit8("bl"),
|
||||
[x8616_ah] = slit8("ah"),
|
||||
[x8616_ch] = slit8("ch"),
|
||||
[x8616_dh] = slit8("dh"),
|
||||
[x8616_bh] = slit8("bh"),
|
||||
};
|
||||
|
||||
RO_ global Str8 x8616_serialize_reg16[] = {
|
||||
[x8616_ax] = slit8("ax"),
|
||||
[x8616_cx] = slit8("cx"),
|
||||
[x8616_dx] = slit8("dx"),
|
||||
[x8616_bx] = slit8("bx"),
|
||||
[x8616_sp] = slit8("sp"),
|
||||
[x8616_bp] = slit8("bp"),
|
||||
[x8616_si] = slit8("si"),
|
||||
[x8616_di] = slit8("di"),
|
||||
};
|
||||
|
||||
RO_ global Str8 x8616_serialize_seg[] = {
|
||||
[x8616_es] = slit8("es"),
|
||||
[x8616_cs] = slit8("cs"),
|
||||
[x8616_ss] = slit8("ss"),
|
||||
[x8616_ds] = slit8("ds"),
|
||||
};
|
||||
|
||||
RO_ global Str8 x8616_serialize_ea[] = {
|
||||
[x8616_ea_bx_si] = slit8("bx + si"),
|
||||
[x8616_ea_bx_di] = slit8("bx + di"),
|
||||
[x8616_ea_bp_si] = slit8("bp + si"),
|
||||
[x8616_ea_bp_di] = slit8("bp + di"),
|
||||
[x8616_ea_si] = slit8("si"),
|
||||
[x8616_ea_di] = slit8("di"),
|
||||
[x8616_ea_bp] = slit8("bp"),
|
||||
[x8616_ea_bx] = slit8("bx"),
|
||||
};
|
||||
|
||||
typedef Enum_(U1, X8616_SerializeSizeWhere) {
|
||||
x8616_serialize_size_none = 0x00,
|
||||
x8616_serialize_size_before_mem = 0x01,
|
||||
x8616_serialize_size_before_imm = 0x02,
|
||||
};
|
||||
|
||||
FI_ B4 x8616_serialize_put(Str8Gen_R gen, Str8 piece) {
|
||||
if (piece.len > gen->cap - gen->len) return false;
|
||||
str8gen_append_str8(gen, piece); return true;
|
||||
}
|
||||
|
||||
FI_ X8616_SerializeStatus x8616_serialize_put_or_full(Str8Gen_R gen, Str8 piece) {
|
||||
X8616_SerializeStatus status = x8616_serialize_ok;
|
||||
if (x8616_serialize_put(gen, piece) == 0) status = x8616_serialize_output_full;
|
||||
return status;
|
||||
}
|
||||
|
||||
internal B4 x8616_serialize_put_u4(Str8Gen_R gen, U4 value) {
|
||||
Info_str8_from_u4 info = str8_from_u4_info(value, 10, 0, 0); UTF8 digits[16];
|
||||
B4 ok = info.size_required != 0 && info.size_required <= Array_len(digits) && info.size_required <= gen->cap - gen->len;
|
||||
if (ok) {
|
||||
Str8 text = str8_from_u4_buf(slice_ut(digits, info.size_required), value, 10, 0, 0, info);
|
||||
ok = x8616_serialize_put(gen, text);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
internal B4 x8616_serialize_put_s4(Str8Gen_R gen, S4 value) {
|
||||
B4 ok = true;
|
||||
if (value < 0) {
|
||||
ok = x8616_serialize_put(gen, slit8("-"));
|
||||
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, -value));
|
||||
}
|
||||
else {
|
||||
ok = x8616_serialize_put_u4(gen, C_(U4, value));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
internal S4 x8616_serialize_s4_from_bits(U2 bits, U1 byte_count) {
|
||||
if (byte_count <= 1) {
|
||||
U4 value = bits & 0xFF;
|
||||
if (value & 0x80) return C_(S4, value) - 256;
|
||||
return C_(S4, value);
|
||||
}
|
||||
U4 value = bits;
|
||||
if (value & 0x8000) return C_(S4, value) - 65536;
|
||||
return C_(S4, value);
|
||||
}
|
||||
|
||||
FI_ B4 x8616_serialize_imm_is_signed(X8616_Op op) { switch (op) {
|
||||
case x8616_op_mov:
|
||||
case x8616_op_add:
|
||||
case x8616_op_adc:
|
||||
case x8616_op_sub:
|
||||
case x8616_op_sbb:
|
||||
case x8616_op_cmp:
|
||||
case x8616_op_ret:
|
||||
case x8616_op_retf:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}}
|
||||
|
||||
FI_ U1 x8616_serialize_imm_bytes(X8616_DecodedOperandFlags flags, U1 immediate_bytes, X8616_WidthMode width) {
|
||||
if (immediate_bytes) return immediate_bytes;
|
||||
if (flags & x8616_decoded_operand_sign_extended) return 1;
|
||||
if (width == x8616_width_word) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
internal B4
|
||||
x8616_serialize_put_imm(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand) {
|
||||
U1 bytes = x8616_serialize_imm_bytes(operand->flags, operand->immediate_bytes, operand->width);
|
||||
if (x8616_serialize_imm_is_signed(inst->op)) {
|
||||
return x8616_serialize_put_s4(gen, x8616_serialize_s4_from_bits(operand->immediate, bytes));
|
||||
}
|
||||
U4 value = operand->immediate;
|
||||
if (bytes <= 1) value &= 0xFF;
|
||||
return x8616_serialize_put_u4(gen, value);
|
||||
}
|
||||
|
||||
internal X8616_WidthMode
|
||||
x8616_serialize_mem_width(X8616_DecodedInstruction_R inst) {
|
||||
for (U1 id = 0; id < inst->operand_count; ++id) {
|
||||
if (inst->operands[id].flags & x8616_decoded_operand_memory) return inst->operands[id].width;
|
||||
}
|
||||
return inst->width;
|
||||
}
|
||||
|
||||
internal X8616_SerializeSizeWhere
|
||||
x8616_serialize_size_where(X8616_Op op, U1 operand_count, X8616_DecodedOperand operands[static 2])
|
||||
{
|
||||
B4 has_mem = 0;
|
||||
B4 has_imm = 0;
|
||||
for (U1 id = 0; id < operand_count; ++id) {
|
||||
X8616_DecodedOperandFlags flags = operands[id].flags;
|
||||
if (flags & x8616_decoded_operand_memory) has_mem = 1;
|
||||
if ((flags & x8616_decoded_operand_immediate) && ((flags & x8616_decoded_operand_register) == 0)) has_imm = 1;
|
||||
}
|
||||
switch (op) {
|
||||
case x8616_op_mov:
|
||||
if (has_mem && has_imm) return x8616_serialize_size_before_imm;
|
||||
return x8616_serialize_size_none;
|
||||
case x8616_op_add:
|
||||
case x8616_op_adc:
|
||||
case x8616_op_sub:
|
||||
case x8616_op_sbb:
|
||||
case x8616_op_cmp:
|
||||
case x8616_op_and:
|
||||
case x8616_op_or:
|
||||
case x8616_op_xor:
|
||||
case x8616_op_test:
|
||||
if (has_mem && has_imm) return x8616_serialize_size_before_mem;
|
||||
return x8616_serialize_size_none;
|
||||
case x8616_op_not:
|
||||
case x8616_op_neg:
|
||||
case x8616_op_inc:
|
||||
case x8616_op_dec:
|
||||
case x8616_op_mul:
|
||||
case x8616_op_imul:
|
||||
case x8616_op_div:
|
||||
case x8616_op_idiv:
|
||||
case x8616_op_push:
|
||||
case x8616_op_pop:
|
||||
case x8616_op_shl:
|
||||
case x8616_op_shr:
|
||||
case x8616_op_sar:
|
||||
case x8616_op_rol:
|
||||
case x8616_op_ror:
|
||||
case x8616_op_rcl:
|
||||
case x8616_op_rcr:
|
||||
if (has_mem) return x8616_serialize_size_before_mem;
|
||||
return x8616_serialize_size_none;
|
||||
default:
|
||||
return x8616_serialize_size_none;
|
||||
}
|
||||
}
|
||||
|
||||
internal B4 x8616_serialize_put_size(Str8Gen_R gen, X8616_WidthMode width) {
|
||||
Str8 name = slit8("");
|
||||
if (width == x8616_width_byte) name = slit8("byte");
|
||||
if (width == x8616_width_word) name = slit8("word");
|
||||
B4 ok = name.len != 0;
|
||||
if (ok) ok = x8616_serialize_put(gen, name);
|
||||
if (ok) ok = x8616_serialize_put(gen, slit8(" "));
|
||||
return ok;
|
||||
}
|
||||
|
||||
internal B4
|
||||
x8616_serialize_put_memory(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand)
|
||||
{
|
||||
B4 ok = true;
|
||||
if (inst->prefixes.has_segment) {
|
||||
ok = x8616_serialize_put(gen, x8616_serialize_seg[inst->prefixes.segment]);
|
||||
if (ok) ok = x8616_serialize_put(gen, slit8(":"));
|
||||
}
|
||||
if (ok) ok = x8616_serialize_put(gen, slit8("["));
|
||||
if (ok && (operand->flags & x8616_decoded_operand_direct)) {
|
||||
ok = x8616_serialize_put_u4(gen, operand->address);
|
||||
}
|
||||
else if (ok) {
|
||||
ok = x8616_serialize_put(gen, x8616_serialize_ea[operand->ea]);
|
||||
S4 disp = operand->displacement;
|
||||
if (ok && disp > 0) {
|
||||
ok = x8616_serialize_put(gen, slit8(" + "));
|
||||
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, disp));
|
||||
}
|
||||
else if (ok && disp < 0) {
|
||||
ok = x8616_serialize_put(gen, slit8(" - "));
|
||||
if (ok) ok = x8616_serialize_put_u4(gen, C_(U4, -disp));
|
||||
}
|
||||
}
|
||||
if (ok) ok = x8616_serialize_put(gen, slit8("]"));
|
||||
return ok;
|
||||
}
|
||||
|
||||
FI_ B4 x8616_serialize_is_string(X8616_Op op) { switch (op) {
|
||||
case x8616_op_movs:
|
||||
case x8616_op_cmps:
|
||||
case x8616_op_scas:
|
||||
case x8616_op_lods:
|
||||
case x8616_op_stos:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}}
|
||||
|
||||
FI_ B4 x8616_serialize_has_memory(X8616_DecodedInstruction_R inst) {
|
||||
for (U1 id = 0; id < inst->operand_count; ++id) { if (inst->operands[id].flags & x8616_decoded_operand_memory) return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal X8616_SerializeStatus
|
||||
x8616_serialize_put_operand(Str8Gen_R gen, X8616_DecodedInstruction_R inst, X8616_DecodedOperand_R operand)
|
||||
{
|
||||
X8616_SerializeStatus status = x8616_serialize_ok;
|
||||
X8616_SerializeSizeWhere where = x8616_serialize_size_where(inst->op, inst->operand_count, inst->operands);
|
||||
X8616_WidthMode width = x8616_serialize_mem_width(inst);
|
||||
B4 is_mem = (operand->flags & x8616_decoded_operand_memory) != 0;
|
||||
B4 is_imm = ((operand->flags & x8616_decoded_operand_immediate) != 0) && ((operand->flags & x8616_decoded_operand_register) == 0);
|
||||
B4 is_reg = (operand->flags & x8616_decoded_operand_register) != 0;
|
||||
B4 is_seg = (operand->flags & x8616_decoded_operand_segment) != 0;
|
||||
B4 is_rel = (operand->flags & x8616_decoded_operand_relative) != 0;
|
||||
B4 is_far = (operand->flags & x8616_decoded_operand_far_ptr) != 0;
|
||||
|
||||
if (status == x8616_serialize_ok && where == x8616_serialize_size_before_mem && is_mem) {
|
||||
if (x8616_serialize_put_size(gen, width) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
if (status == x8616_serialize_ok && where == x8616_serialize_size_before_imm && is_imm) {
|
||||
if (x8616_serialize_put_size(gen, width) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
if (status == x8616_serialize_ok && (inst->flags & x8616_encoding_far) && is_mem) {
|
||||
status = x8616_serialize_put_or_full(gen, slit8("far "));
|
||||
}
|
||||
|
||||
if (status == x8616_serialize_ok) {
|
||||
if (is_reg) {
|
||||
U1 index = C_(U1, operand->reg.r16);
|
||||
if (operand->width == x8616_width_byte) status = x8616_serialize_put_or_full(gen, x8616_serialize_reg8 [index]);
|
||||
else if (operand->width == x8616_width_word) status = x8616_serialize_put_or_full(gen, x8616_serialize_reg16[index]);
|
||||
else status = x8616_serialize_unsupported_form;
|
||||
}
|
||||
else if (is_seg) {
|
||||
status = x8616_serialize_put_or_full(gen, x8616_serialize_seg[operand->segment]);
|
||||
}
|
||||
else if (is_mem) {
|
||||
if (x8616_serialize_put_memory(gen, inst, operand) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
else if (is_imm) {
|
||||
if (x8616_serialize_put_imm(gen, inst, operand) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
else if (is_rel) {
|
||||
S4 rel = C_(S4, inst->size) + operand->displacement;
|
||||
status = x8616_serialize_put_or_full(gen, slit8("$"));
|
||||
if (status == x8616_serialize_ok && rel >= 0) status = x8616_serialize_put_or_full(gen, slit8("+"));
|
||||
if (status == x8616_serialize_ok && x8616_serialize_put_s4(gen, rel) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
else if (is_far) {
|
||||
if (x8616_serialize_put_u4(gen, operand->far_segment) == 0) status = x8616_serialize_output_full;
|
||||
if (status == x8616_serialize_ok) status = x8616_serialize_put_or_full(gen, slit8(":"));
|
||||
if (status == x8616_serialize_ok && x8616_serialize_put_u4(gen, operand->far_offset) == 0) status = x8616_serialize_output_full;
|
||||
}
|
||||
else {
|
||||
status = x8616_serialize_unsupported_form;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
FI_ X8616_DecodedOperandFlags x8616_serialize_base_flags(X8616_DecodedOperandFlags flags) {
|
||||
return flags & (
|
||||
x8616_decoded_operand_register
|
||||
| x8616_decoded_operand_segment
|
||||
| x8616_decoded_operand_memory
|
||||
| x8616_decoded_operand_immediate
|
||||
| x8616_decoded_operand_relative
|
||||
| x8616_decoded_operand_far_ptr
|
||||
);
|
||||
}
|
||||
|
||||
FI_ B4 x8616_serialize_one_flag(X8616_DecodedOperandFlags flags) { U2 bits = C_(U2, flags); return (bits != 0) && ((bits & (bits - 1)) == 0); }
|
||||
|
||||
internal void
|
||||
x8616_serialize_push(FArena_R arena, X8616_InfoList_R msgs, X8616_SerializeStatus status, U4 id, U2 size, U4 expected, U4 actual) {
|
||||
if (status == x8616_serialize_ok || arena == 0) return;
|
||||
X8616_InfoKind kind = x8616_info_error;
|
||||
X8616_InfoCode code = x8616_info_serialize_invalid_record;
|
||||
if (status == x8616_serialize_output_full) {
|
||||
kind = x8616_info_warning;
|
||||
code = x8616_info_serialize_output_full;
|
||||
}
|
||||
else if (status == x8616_serialize_unsupported_form) {
|
||||
code = x8616_info_serialize_unsupported_form;
|
||||
}
|
||||
x8616_info_push(arena, msgs, kind, code, id, size, expected, actual);
|
||||
}
|
||||
|
||||
internal X8616_SerializeStatus
|
||||
x8616_serialize_validate(X8616_DecodedInstruction_R inst)
|
||||
{
|
||||
X8616_SerializeStatus status = x8616_serialize_ok;
|
||||
|
||||
B4 bad_decode = inst->decode_flags & (x8616_decode_invalid | x8616_decode_truncated);
|
||||
B4 invalid_sig = inst->size == 0 || inst->operand_count > 2;
|
||||
B4 invalid_mnemonic = u4_(inst->op) >= Array_len(x8616_serialize_mnemonic) || inst->op == x8616_op_invalid;
|
||||
B4 invalid_prefix_with_seg = inst->prefixes.has_segment && u1_(inst->prefixes.segment) >= Array_len(x8616_serialize_seg);
|
||||
|
||||
if (bad_decode || invalid_sig || invalid_mnemonic || invalid_prefix_with_seg) {
|
||||
status = x8616_serialize_invalid_record; goto status_failed;
|
||||
}
|
||||
B4 bad_prefix_segement = inst->prefixes.has_segment && (x8616_serialize_has_memory(inst) == 0);
|
||||
B4 bad_prefix_repeat = inst->prefixes.has_repeat && (x8616_serialize_is_string(inst->op) == 0);
|
||||
if (bad_prefix_segement || bad_prefix_repeat) {
|
||||
status = x8616_serialize_unsupported_form; goto status_failed;
|
||||
}
|
||||
|
||||
for (U1 id = 0; id < inst->operand_count; ++id)
|
||||
{
|
||||
X8616_DecodedOperand_R operand = & inst->operands[id];
|
||||
X8616_DecodedOperandFlags base = x8616_serialize_base_flags(operand->flags);
|
||||
B4 invalid_flag = x8616_serialize_one_flag(base) == 0;
|
||||
B4 has_operand_register = base & x8616_decoded_operand_register;
|
||||
B4 has_operand_segment = base & x8616_decoded_operand_segment;
|
||||
B4 has_operand_memory = base & x8616_decoded_operand_memory;
|
||||
B4 invalid_reg_r16 = u1_(operand->reg.r16) >= Array_len(x8616_serialize_reg16);
|
||||
B4 invalid_width = operand->width != x8616_width_byte && operand->width != x8616_width_word;
|
||||
B4 invalid_operand_seg = u1_(operand->segment) >= Array_len(x8616_serialize_seg);
|
||||
B4 invalid_operand_ea = u1_(operand->ea) >= Array_len(x8616_serialize_ea);
|
||||
B4 invalid_direct_ea = has_operand_memory && ((operand->flags & x8616_decoded_operand_direct) == 0) && invalid_operand_ea;
|
||||
B4 invalid_operand = invalid_flag
|
||||
|| (has_operand_register && (invalid_reg_r16 || invalid_width))
|
||||
|| (has_operand_segment && invalid_operand_seg)
|
||||
|| invalid_direct_ea;
|
||||
if (invalid_operand) {
|
||||
status = x8616_serialize_invalid_record; goto status_failed;
|
||||
}
|
||||
}
|
||||
status_failed:
|
||||
return status;
|
||||
}
|
||||
|
||||
internal X8616_SerializeStatus
|
||||
x8616_serialize_instruction_line(Str8Gen_R line, X8616_DecodedInstruction* inst)
|
||||
{
|
||||
X8616_SerializeStatus st = x8616_serialize_ok;
|
||||
Str8 mnemonic = x8616_serialize_mnemonic[inst->op];
|
||||
if (mnemonic.len == 0) st = x8616_serialize_unsupported_form;
|
||||
|
||||
if (st == x8616_serialize_ok && inst->prefixes.lock) {
|
||||
st = x8616_serialize_put_or_full(line, slit8("lock "));
|
||||
}
|
||||
if (st == x8616_serialize_ok && inst->prefixes.has_repeat) {
|
||||
if (inst->prefixes.repeat == x8616_rep) st = x8616_serialize_put_or_full(line, slit8("rep "));
|
||||
else st = x8616_serialize_put_or_full(line, slit8("repne "));
|
||||
}
|
||||
if (st == x8616_serialize_ok) st = x8616_serialize_put_or_full(line, mnemonic);
|
||||
|
||||
if (st == x8616_serialize_ok && x8616_serialize_is_string(inst->op)) {
|
||||
if (inst->width == x8616_width_byte) st = x8616_serialize_put_or_full(line, slit8("b"));
|
||||
else if (inst->width == x8616_width_word) st = x8616_serialize_put_or_full(line, slit8("w"));
|
||||
else st = x8616_serialize_unsupported_form;
|
||||
}
|
||||
|
||||
if (st == x8616_serialize_ok && inst->operand_count) {
|
||||
st = x8616_serialize_put_or_full(line, slit8(" "));
|
||||
for (U1 id = 0; st == x8616_serialize_ok && id < inst->operand_count; ++id) {
|
||||
if (id) st = x8616_serialize_put_or_full(line, slit8(", "));
|
||||
if (st == x8616_serialize_ok) st = x8616_serialize_put_operand(line, inst, & inst->operands[id]);
|
||||
}
|
||||
}
|
||||
if (st == x8616_serialize_ok) st = x8616_serialize_put_or_full(line, slit8("\n"));
|
||||
return st;
|
||||
}
|
||||
|
||||
X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request)
|
||||
{
|
||||
X8616_SerializeInfo result = {0}; result.text.ptr = C_(UTF8*, request.output.ptr);
|
||||
X8616_InfoList local = {0};
|
||||
X8616_InfoList_R msgs = request.msgs ? request.msgs : & local;
|
||||
|
||||
B4 bad_request =
|
||||
(request.instruction_count && request.instructions == 0)
|
||||
|| (request.output.len && request.output.ptr == 0)
|
||||
|| (request.scratch.len && request.scratch.ptr == 0)
|
||||
|| (request.info_arena == 0);
|
||||
if (bad_request)
|
||||
{
|
||||
if (request.info_arena) {
|
||||
x8616_info_push(request.info_arena, msgs, x8616_info_error
|
||||
, x8616_info_serialize_bad_request, 0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
msgs->count += 1;
|
||||
msgs->error_count += 1;
|
||||
msgs->dropped_count += 1;
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
if (request.output.len < x8616_serialize_header.len) {
|
||||
x8616_serialize_push(request.info_arena, msgs, x8616_serialize_output_full
|
||||
, 0, 0, u4_(x8616_serialize_header.len), u4_(request.output.len));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Str8Gen gen = str8gen_make(request.output);
|
||||
str8gen_append_str8(& gen, x8616_serialize_header);
|
||||
result.text.len = gen.len;
|
||||
|
||||
for (U4 id = 0; id < request.instruction_count; ++id)
|
||||
{
|
||||
X8616_DecodedInstruction_R inst = & request.instructions[id];
|
||||
X8616_SerializeStatus line_status = x8616_serialize_validate(inst);
|
||||
if (line_status != x8616_serialize_ok) {
|
||||
x8616_serialize_push(request.info_arena, msgs, line_status
|
||||
, id, inst->size, 0, u4_(inst->op));
|
||||
continue;
|
||||
}
|
||||
|
||||
Str8Gen line = str8gen_make(request.scratch);
|
||||
line_status = x8616_serialize_instruction_line(& line, inst);
|
||||
if (line_status != x8616_serialize_ok) {
|
||||
x8616_serialize_push(request.info_arena, msgs, line_status
|
||||
, id, inst->size, u4_(request.scratch.len), u4_(line.len));
|
||||
continue;
|
||||
}
|
||||
|
||||
Str8 text = str8(line.ptr, line.len);
|
||||
if (text.len > gen.cap - gen.len) {
|
||||
x8616_serialize_push(request.info_arena, msgs, x8616_serialize_output_full
|
||||
, id, inst->size, u4_(request.output.len), u4_(gen.len));
|
||||
goto exit;
|
||||
}
|
||||
str8gen_append_str8(& gen, text);
|
||||
result.text.len = gen.len;
|
||||
result.instructions_written += 1;
|
||||
}
|
||||
|
||||
exit:
|
||||
result.msgs = *msgs;
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "decoder.h"
|
||||
#endif
|
||||
|
||||
typedef Enum_(U1, X8616_SerializeStatus) {
|
||||
x8616_serialize_ok = 0x00,
|
||||
x8616_serialize_output_full = 0x01,
|
||||
x8616_serialize_invalid_record = 0x02,
|
||||
x8616_serialize_unsupported_form = 0x03,
|
||||
};
|
||||
|
||||
typedef Struct_(X8616_SerializeRequest) {
|
||||
X8616_DecodedInstruction* instructions;
|
||||
U4 instruction_count; byte_pad(4);
|
||||
Slice output;
|
||||
Slice scratch;
|
||||
FArena* info_arena;
|
||||
X8616_InfoList_R msgs;
|
||||
};
|
||||
|
||||
typedef Struct_(X8616_SerializeInfo) {
|
||||
X8616_InfoList msgs;
|
||||
Str8 text;
|
||||
U4 instructions_written;
|
||||
byte_pad(4);
|
||||
};
|
||||
|
||||
X8616_SerializeInfo x8616_serialize_instructions(X8616_SerializeRequest request);
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
FI_ 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;
|
||||
}
|
||||
|
||||
FI_ 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;
|
||||
}
|
||||
|
||||
FI_ 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 8–15 stay 0 */
|
||||
}
|
||||
|
||||
FI_ 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 */
|
||||
}
|
||||
|
||||
FI_ 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;
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
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 clang diagnostic ignored "-Wmicrosoft-fixed-enum"
|
||||
// #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
|
||||
|
||||
#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) enum symbol : underlying_type TSet_(symbol); enum symbol : underlying_type
|
||||
#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 jump_ne(a,b,label) if (a != b) goto label
|
||||
#define jump_gt(a,b,label) if (a > b) goto label
|
||||
#define jump_lt(a,b,label) if (a < b) goto label
|
||||
|
||||
#define unreachable() __builtin_unreachable()
|
||||
|
||||
#define 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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "duffle/dsl.h"
|
||||
#include "duffle/asm.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/encoder.h"
|
||||
#include "8086/encoder_table.h"
|
||||
#include "8086/info.h"
|
||||
#include "8086/info_render.h"
|
||||
#include "8086/decoder.h"
|
||||
#include "8086/serializer.h"
|
||||
#include "8086/gen/decoder_table.h"
|
||||
|
||||
#include "8086/decoder.c"
|
||||
#include "8086/serializer.c"
|
||||
|
||||
// #include "8086/decoder.h"
|
||||
|
||||
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; }
|
||||
|
||||
|
||||
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(16),
|
||||
FileRam_Len = kilo(16),
|
||||
};
|
||||
typedef Struct_(SMemory) {
|
||||
U1 Scratchpad [Scratchpad_Len];
|
||||
U1 FileRam [FileRam_Len];
|
||||
|
||||
U1 decode_mem[kilo(64)];
|
||||
UTF8 text_mem [kilo(16)];
|
||||
};
|
||||
global SMemory smem;
|
||||
|
||||
#define path_course_content "./course_content/perfaware/"
|
||||
#define path_part1 path_course_content "part1/"
|
||||
|
||||
typedef Slice_(X8616_DecodedInstruction);
|
||||
|
||||
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);
|
||||
farena_reset(& scratch);
|
||||
|
||||
FArena decode_arena = farena_make(slice_ut_arr(smem.decode_mem));
|
||||
Slice_X8616_DecodedInstruction decoded = farena_push_array(& decode_arena, X8616_DecodedInstruction, data.len);
|
||||
|
||||
X8616_DecodeInfo info = x8616_decode_(
|
||||
.source = data.ptr,
|
||||
.source_len = data.len,
|
||||
.out_instructions = decoded.ptr,
|
||||
.instruction_cap = decoded.len,
|
||||
.info_arena = & decode_arena,
|
||||
);
|
||||
if (info.source_consumed != data.len || info.instruction_count == 0 || info.msgs.error_count || info.msgs.dropped_count) {
|
||||
ms_exit_process(10);
|
||||
return 10;
|
||||
}
|
||||
X8616_SerializeInfo text = x8616_serialize_instructions((X8616_SerializeRequest){
|
||||
.instructions = decoded.ptr,
|
||||
.instruction_count = info.instruction_count,
|
||||
.output = slice_ut_arr(smem.text_mem),
|
||||
.scratch = slice_ut_arr(smem.Scratchpad),
|
||||
.info_arena = & decode_arena,
|
||||
.msgs = & info.msgs,
|
||||
});
|
||||
if (text.msgs.error_count || text.msgs.dropped_count || text.instructions_written != info.instruction_count) {
|
||||
ms_exit_process(13);
|
||||
return 13;
|
||||
}
|
||||
Str8 listing_text = text.text;
|
||||
(void)listing_text;
|
||||
|
||||
ms_exit_process(0);
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 451 KiB |
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
|
||||
Binary file not shown.
@@ -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 )
|
||||
@@ -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.
@@ -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
|
||||
@@ -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>
|
||||
@@ -0,0 +1,14 @@
|
||||
// raddbg 0.9.28 project file
|
||||
|
||||
target:
|
||||
{
|
||||
executable: "build/sim_8086.exe"
|
||||
working_directory: "../perfaware"
|
||||
label: "Sim 8086"
|
||||
enabled: 1
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/decoder_table_generator.meta.exe"
|
||||
working_directory: "../perfaware"
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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.'
|
||||
Vendored
-100
@@ -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
|
||||
...
|
||||
Vendored
-82
@@ -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
|
||||
}
|
||||
Vendored
-18369
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user