Compare commits

..
5 Commits
Author SHA1 Message Date
ed aa9c4d48f6 starting to prep to decode instructions 2026-08-07 10:01:20 -04:00
ed 823ec3d499 Add update_deps.ps1 (clone computer enhance repo) 2026-08-07 01:32:51 -04:00
ed 77bda7741f Picture! 2026-08-07 01:08:26 -04:00
ed 8b4c8a2c71 got file reading working for the binary. 2026-08-07 01:06:57 -04:00
ed 6feff68b33 Some more prep 2026-08-06 21:10:04 -04:00
20 changed files with 701 additions and 100 deletions
+3
View File
@@ -0,0 +1,3 @@
code/8086/* linguist-language=C
code/duffle/* linguist-language=C
code/part_1/* linguist-language=C
+1
View File
@@ -1 +1,2 @@
build
course_content
+16
View File
@@ -0,0 +1,16 @@
# Computer Enhance: Performance Aware Programming Course
Progressing with company team.
Disable latency of submodules:
```ps1
git -C . config --local diff.ignoreSubmodules all
git -C . config --local status.submoduleSummary false
git -C . config --local submodule.recurse false
```
## Gallery
Part 1: File read!
![Part 1: File read!](./docs/assets/raddbg_2026-08-07_01-06-36.png)
+10
View File
@@ -6,3 +6,13 @@ 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
```
+4
View File
@@ -14,4 +14,8 @@
#else
#define assert(cond)
#endif
#define trap() __builtin_trap()
#define assert_always(x) do { if((x) == false) {trap();} } while(0)
#pragma endregion Debug
+87 -20
View File
@@ -9,6 +9,7 @@ Standard: c23
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wuninitialized"
#pragma clang diagnostic ignored "-Wmicrosoft-enum-forward-reference"
// #pragma comment(lib, "Advapi32.lib")
// #pragma comment(lib, "gdi32.lib")
// #pragma comment(lib, "Kernel32.lib")
@@ -16,8 +17,19 @@ Standard: c23
// #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__
@@ -206,14 +218,17 @@ def_signed_ops(le, <=)
#define dbg_args(...) __VA_ARGS__
#pragma region Control Flow & Iteration
#define unreachable() __builtin_unreachable()
#define each_iter(type, iter, end) (type iter = 0; iter < end; ++ iter)
#define index_iter(type, iter, begin, op, end) (type iter = begin; iter op end; (begin < end ? ++ iter : -- iter))
#define range_iter(iter,op,range) (T_((range).p0) iter = (range).p0; iter op (range).p1; ((range).p0 < (range).p1 ? ++ iter : -- iter))
#define defer(expr) for(U4 once= 1; once!=1;++ once,(expr)) // Basic do something after body
#define scope(begin,end) for(U4 once=(1,(begin)); once!=1;++ once,(end )) // Do things before or after a scope
#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 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)
@@ -232,28 +247,80 @@ def_signed_ops(le, <=)
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
#pragma region Math
#define u8_max 0xffffffffffffffffull
// 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
#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"
#pragma region Misc
enum {
Bitmask_3 = 0x00000007,
Bitmask_4 = 0x0000000f,
Bitmask_5 = 0x0000001f,
Bitmask_6 = 0x0000003f,
Bitmask_10 = 0x000003ff,
};
#define clamp_decrement(X) (((X) > 0) ? ((X) - 1) : 0)
typedef Enum_(U4, WeekDay) {
WeekDay_Sun,
WeekDay_Mon,
WeekDay_Tue,
WeekDay_Wed,
WeekDay_Thu,
WeekDay_Fri,
WeekDay_Sat,
WeekDay_Num,
};
typedef Struct_(R1_U1){ U1 p0; U1 p1; };
typedef Struct_(R1_U2){ U2 p0; U2 p1; };
typedef Struct_(R1_U4){ U4 p0; U2 p4; };
typedef Struct_(R1_U8){ U8 p0; U8 p4; };
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 Struct_(V2_U1){ U1 x; U1 y;};
typedef U8 DenseTime;
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); }
#pragma endregion Math
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
+63 -2
View File
@@ -3,9 +3,70 @@
# include "dsl.h"
#endif
#pragma region Encoding
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; }
}
#pragma endregion Encoding
internal 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;
}
+70
View File
@@ -0,0 +1,70 @@
#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);
internal 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) {
farena_rewind(arena, pre_pos + actual_read_size); 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(); }
CLANG_OPTIMIZE_ENABLE
+1
View File
@@ -2,6 +2,7 @@
# pragma once
# include "dsl.h"
# include "memory.h"
# include "analysis.h"
#endif
#pragma region Hashing
+43
View File
@@ -0,0 +1,43 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "analysis.h"
#endif
#pragma region Math
#define u8_max 0xffffffffffffffffull
#define min(A,B) (((A) < (B)) ? (A) : (B))
#define max(A,B) (((A) > (B)) ? (A) : (B))
#define clamp_bot(X,B) max(X, B) // Clamp "X" by "B"
#define clamp_decrement(X) (((X) > 0) ? ((X) - 1) : 0)
typedef Struct_(R1_U1){ U1 p0; U1 p1; };
typedef Struct_(R1_U2){ U2 p0; U2 p1; };
typedef Struct_(R1_U4){ U4 p0; U2 p1; };
typedef Struct_(R1_U8){ U8 p0; U8 p1; };
#define r1u4(p0,p1) (R1_U4){p0,p1}
#define r1u8(p0,p1) (R1_U8){p0,p1}
typedef Struct_(V2_U1){ U1 x; U1 y;};
FI_ B8 add_of (U8 a, U8 b, U8*R_ res) { return __builtin_uaddll_overflow(a, b, res); }
FI_ B8 sub_of (U8 a, U8 b, U8*R_ res) { return __builtin_usubll_overflow(a, b, res); }
FI_ B8 mul_of (U8 a, U8 b, U8*R_ res) { return __builtin_umulll_overflow(a, b, res); }
FI_ B8 add_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_saddll_overflow(a, b, res); }
FI_ B8 sub_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_ssubll_overflow(a, b, res); }
FI_ B8 mul_s_of(S8 a, S8 b, S8*R_ res) { return __builtin_smulll_overflow(a, b, res); }
FI_ U8 span_r1u8(R1_U8 r) {U8 c = ((r.p1 > r.p0) ? (r.p1 - r.p0) : 0); return c;}
#pragma endregion Math
#pragma region Numerics
enum {
Max_U4 = 0xffffffff
};
FI_ U2 Csafe_u2u4(U4 x) { assert_always(x <= Max_U4); return C_(U2, x); }
#pragma endregion Numerics
+15 -6
View File
@@ -33,6 +33,11 @@ FI_ U8 mem_copy_overlapping(U8 dest, U8 src, U8 len) { return (U8)(__builtin_m
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]))
#pragma region DAG
#define check_nil(nil, p) ((p) == 0 || (p) == nil)
@@ -63,22 +68,22 @@ 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; }
typedef Slice_(B1);
#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_(u4_(ptr), u4_(len))
#define slice_ut_arr(a) slice_ut_(u4_(a), S_(a))
#define slice_to_ut(s) slice_ut_(u4_((s).ptr), S_slice(s))
#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_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); }
@@ -91,11 +96,15 @@ FI_ void slice_copy_(Slice dest, Slice src) {
mem_copy(dest.ptr, src.ptr, src.len);
}
#define slice_copy(dest, src) do { \
static_assert(T_same(dest, src)); \
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
+1
View File
@@ -3,6 +3,7 @@
# include "dsl.h"
# include "memory.h"
# include "hashing.h"
# include "analysis.h"
#endif
#pragma region Key Table Linear (KTL)
+30 -1
View File
@@ -2,12 +2,14 @@
# pragma once
# include "dsl.h"
# include "memory.h"
# include "encoding.h"
# include "hashing.h"
# include "tables.h"
# include "analysis.h"
#endif
// NOTE(rjf): Includes reverses for uppercase and lowercase hex.
RO_ global U8 integer_symbol_reverse[128] = {
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,
@@ -203,3 +205,30 @@ FI_ void str8gen_append_fmt(Str8Gen_R gen, Str8 fmt, KTL_Str8 tbl) {
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 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; farena_rewind(arena, (cap - size) * 2);
result = str16(C_(UTF16*, str.ptr), size);
}
return result;
}
+171 -13
View File
@@ -17,6 +17,50 @@ 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);
@@ -35,6 +79,7 @@ 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");
@@ -52,6 +97,13 @@ WinAPI B4 ms_write_console(
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");
@@ -112,11 +164,28 @@ WinAPI S4 ms_set_bk_mode(void* hdc, S4 mode) asm("
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,
@@ -133,26 +202,115 @@ enum {
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_PAGE_EXECUTE_READWRITE = 0x40,
MS_WM_CHAR = 0x0102,
MS_VK_RETURN = 0x0D,
MS_VK_BACK = 0x08,
MS_VK_TAB = 0x09,
MS_VK_SPACE = 0x20,
MS_VK_F1 = 0x70,
MS_VK_F2 = 0x71,
MS_VK_F5 = 0x74,
MS_VK_PRIOR = 0x21,
MS_VK_NEXT = 0x22,
MS_VK_SHIFT =0x10,
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 = 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};
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;
}
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;
}
#endif
+78
View File
@@ -1,10 +1,88 @@
#include "duffle/dsl.h"
#include "duffle/analysis.h"
#include "duffle/math.h"
#include "duffle/memory.h"
#include "duffle/hashing.h"
#include "duffle/encoding.h"
#include "duffle/tables.h"
#include "duffle/text.h"
#include "duffle/files.h"
#include "duffle/win32.h"
typedef Struct_(U2_HL) { U1 Low; U1 High; };
#define bitmask_(pos) (1 << pos)
#define bit_isolate(bitfield, pos) (bitmask_(pos) & value)
#define serialize_bit(bitfield, pos) (bit_isolate(bitfield, pos) == bitmask_(pos) ? '1' : '0')
typedef Enum_(U4, Endieaness) {
Little,
Big,
};
FI_ void a8utf8_from_u1_le(UTF8 out[8], U1 value) {
out[0] = serialize_bit(value, 7);
out[1] = serialize_bit(value, 6);
out[2] = serialize_bit(value, 5);
out[3] = serialize_bit(value, 4);
out[4] = serialize_bit(value, 3);
out[5] = serialize_bit(value, 2);
out[6] = serialize_bit(value, 1);
out[7] = serialize_bit(value, 0);
}
FI_ void a8utf8_from_u1_be(UTF8 out[8], U1 value) {
out[0] = serialize_bit(value, 0);
out[1] = serialize_bit(value, 1);
out[2] = serialize_bit(value, 2);
out[3] = serialize_bit(value, 3);
out[4] = serialize_bit(value, 4);
out[5] = serialize_bit(value, 5);
out[6] = serialize_bit(value, 6);
out[7] = serialize_bit(value, 7);
}
I_ U4 binary_as_str8_eval_len(Slice_U1 data) { return data.len * 8; }
#define jump_lt(a,b,label) if (a < b) goto label
I_ Str8 binary_as_str8(Slice_U1 data, FArena* str8_mem) { Str8 result = {0};
U4 req_len = data.len * 8; jump_lt(str8_mem->capacity,req_len, jret);
result = farena_push_array(str8_mem, UTF8, req_len);
for index_iter(U4,cursor, 0,<,req_len) { a8utf8_from_u1_le(result.ptr + cursor, data.ptr[cursor]); }
jret: return result;
}
typedef Enum_(U4, x86_Op) {
x86_mov
};
enum {
Scratchpad_Len = kilo(1),
FileRam_Len = kilo(16),
};
typedef Struct_(SMemory) {
U1 Scratchpad [Scratchpad_Len];
U1 FileRam [FileRam_Len];
};
global SMemory smem;
#define path_course_content "./course_content/perfaware/"
#define path_part1 path_course_content "part1/"
CLANG_OPTIMIZE_DISABLE
int main()
{
FArena scratch = farena_make(slice_ut_arr(smem.Scratchpad));
FArena file_arena = farena_make(slice_ut_arr(smem.FileRam));
Str8 path_listing_0037_single_register_mov = slit8(path_part1 "listing_0037_single_register_mov");
Str8 path_listing_0037_single_register_mov_asm = slit8(path_part1 "listing_0037_single_register_mov.asm");
Slice_U1 data = data_from_file_path(& file_arena, path_listing_0037_single_register_mov, & scratch);
ms_exit_process(0);
return 0;
}
CLANG_OPTIMIZE_ENABLE
Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

+9
View File
@@ -0,0 +1,9 @@
// raddbg 0.9.28 project file
target:
{
executable: "build/sim_8086.exe"
working_directory: ""
enabled: 1
label: "Sim 8086"
}
+10 -3
View File
@@ -278,6 +278,7 @@ $libraries_win32 = @(
'kernel32.lib'
'user32.lib'
'gdi32.lib'
'vcruntime.lib'
)
# --- Functions ---
@@ -291,11 +292,12 @@ function compile-unit {
)
$compile_args = @()
$compile_args += $f_std_c11
$compile_args += $f_all_c
$compile_args += $f_ms_ex
$compile_args += $f_wall
$compile_args += $f_wno_attributes
$compile_args += $f_exceptions_disabled
$compile_args += $f_diagnostics_absolute
$compile_args += $f_optimize_none
$compile_args += $f_debug
foreach ($p in $include_paths) {
$compile_args += ($f_include + $p)
@@ -306,7 +308,8 @@ function compile-unit {
$compile_args += ($f_output + $link_module)
write-host "Compiling '$unit' -> '$link_module'" -ForegroundColor DarkCyan
& $compiler $compile_args
$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 }
}
@@ -340,7 +343,8 @@ function link-modules {
$link_args += $user_link_args
write-host "Linking modules into '$module'" -ForegroundColor DarkCyan
& $linker $link_args
$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 }
}
@@ -355,6 +359,9 @@ function build-part_1 {
$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
+11 -2
View File
@@ -1,6 +1,15 @@
function clone-gitrepo { param( [string] $path, [string] $url )
function clone-gitrepo { param( [string] $path, [string] $url, [switch] $NoPull )
if (test-path $path) {
# git -C $path pull
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 ..."
+25
View File
@@ -0,0 +1,25 @@
# ════════════════════════════════════════════════════════════════════════════
# update_deps.ps1 — fetch / refresh.
# ════════════════════════════════════════════════════════════════════════════
param(
[switch] $NoPull # Skip the `git pull` step when the checkout already exists.
)
$path_root = split-path -Path $PSScriptRoot -Parent
$path_course_content = join-path $path_root 'course_content'
$misc = join-path $PSScriptRoot 'helpers/misc.ps1'; . $misc
# Halt on any error (instead of PowerShell's default `Continue`).
$ErrorActionPreference = 'Stop'
# --- Dependency Definition ---
# One external dep for now: Casey Muratori's computer_enhance course repo.
$url_computer_enhance = 'https://github.com/cmuratori/computer_enhance.git'
# --- Run ---
if ($NoPull) { clone-gitrepo $path_course_content $url_computer_enhance -NoPull }
else { clone-gitrepo $path_course_content $url_computer_enhance }
write-host ''
write-host 'Course content up to date.'