diff --git a/perfaware/part3/listing_0144_read_unroll.asm b/perfaware/part3/listing_0144_read_unroll.asm new file mode 100644 index 00000000..e4293015 --- /dev/null +++ b/perfaware/part3/listing_0144_read_unroll.asm @@ -0,0 +1,65 @@ +; ======================================================================== +; +; (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 more information +; +; ======================================================================== + +; ======================================================================== +; LISTING 144 +; ======================================================================== + +global Read_x1 +global Read_x2 +global Read_x3 +global Read_x4 + +section .text + +; +; NOTE(casey): These ASM routines are written for the Windows +; 64-bit ABI. They expect the count in rcx and the data pointer in rdx. +; + +Read_x1: + align 64 +.loop: + mov rax, [rdx] + sub rcx, 1 + jnle .loop + ret + +Read_x2: + align 64 +.loop: + mov rax, [rdx] + mov rax, [rdx] + sub rcx, 2 + jnle .loop + ret + +Read_x3: + align 64 +.loop: + mov rax, [rdx] + mov rax, [rdx] + mov rax, [rdx] + sub rcx, 3 + jnle .loop + ret + +Read_x4: + align 64 +.loop: + mov rax, [rdx] + mov rax, [rdx] + mov rax, [rdx] + mov rax, [rdx] + sub rcx, 4 + jnle .loop + ret diff --git a/perfaware/part3/listing_0145_read_unroll_main.cpp b/perfaware/part3/listing_0145_read_unroll_main.cpp new file mode 100644 index 00000000..a1eb44be --- /dev/null +++ b/perfaware/part3/listing_0145_read_unroll_main.cpp @@ -0,0 +1,105 @@ +/* ======================================================================== + + (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 more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 145 + ======================================================================== */ + +/* NOTE(casey): _CRT_SECURE_NO_WARNINGS is here because otherwise we cannot + call fopen(). If we replace fopen() with fopen_s() to avoid the warning, + then the code doesn't compile on Linux anymore, since fopen_s() does not + exist there. + + What exactly the CRT maintainers were thinking when they made this choice, + I have no idea. */ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int32_t b32; + +typedef float f32; +typedef double f64; + +#define ArrayCount(Array) (sizeof(Array)/sizeof((Array)[0])) + +#include "listing_0125_buffer.cpp" +#include "listing_0137_os_platform.cpp" +#include "listing_0109_pagefault_repetition_tester.cpp" + +typedef void ASMFunction(u64 Count, u8 *Data); + +extern "C" void Read_x1(u64 Count, u8 *Data); +extern "C" void Read_x2(u64 Count, u8 *Data); +extern "C" void Read_x3(u64 Count, u8 *Data); +extern "C" void Read_x4(u64 Count, u8 *Data); +#pragma comment (lib, "listing_0144_read_unroll") + +struct test_function +{ + char const *Name; + ASMFunction *Func; +}; +test_function TestFunctions[] = +{ + {"Read_x1", Read_x1}, + {"Read_x2", Read_x2}, + {"Read_x3", Read_x3}, + {"Read_x4", Read_x4}, +}; + +int main(void) +{ + InitializeOSPlatform(); + + u64 RepeatCount = 1024*1024*1024ull; + buffer Buffer = AllocateBuffer(4096); + if(IsValid(Buffer)) + { + repetition_tester Testers[ArrayCount(TestFunctions)] = {}; + for(;;) + { + for(u32 FuncIndex = 0; FuncIndex < ArrayCount(TestFunctions); ++FuncIndex) + { + repetition_tester *Tester = &Testers[FuncIndex]; + test_function TestFunc = TestFunctions[FuncIndex]; + + printf("\n--- %s ---\n", TestFunc.Name); + NewTestWave(Tester, RepeatCount, GetCPUTimerFreq()); + + while(IsTesting(Tester)) + { + BeginTime(Tester); + TestFunc.Func(RepeatCount, Buffer.Data); + EndTime(Tester); + CountBytes(Tester, RepeatCount); + } + } + } + } + else + { + fprintf(stderr, "Unable to allocate memory buffer for testing"); + } + + FreeBuffer(&Buffer); + + return 0; +} diff --git a/perfaware/part3/listing_0146_byte_read.asm b/perfaware/part3/listing_0146_byte_read.asm new file mode 100644 index 00000000..515fae14 --- /dev/null +++ b/perfaware/part3/listing_0146_byte_read.asm @@ -0,0 +1,44 @@ +; ======================================================================== +; +; (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 more information +; +; ======================================================================== + +; ======================================================================== +; LISTING 146 +; ======================================================================== + +global Read_1x2 +global Read_8x2 + +section .text + +; +; NOTE(casey): These ASM routines are written for the Windows +; 64-bit ABI. They expect the count in rcx and the data pointer in rdx. +; + +Read_1x2: + align 64 +.loop: + mov al, [rdx] + mov al, [rdx] + sub rcx, 2 + jnle .loop + ret + +Read_8x2: + align 64 +.loop: + mov rax, [rdx] + mov rax, [rdx] + sub rcx, 2 + jnle .loop + ret + diff --git a/perfaware/part3/listing_0147_byte_read_main.cpp b/perfaware/part3/listing_0147_byte_read_main.cpp new file mode 100644 index 00000000..becc527e --- /dev/null +++ b/perfaware/part3/listing_0147_byte_read_main.cpp @@ -0,0 +1,101 @@ +/* ======================================================================== + + (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 more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 147 + ======================================================================== */ + +/* NOTE(casey): _CRT_SECURE_NO_WARNINGS is here because otherwise we cannot + call fopen(). If we replace fopen() with fopen_s() to avoid the warning, + then the code doesn't compile on Linux anymore, since fopen_s() does not + exist there. + + What exactly the CRT maintainers were thinking when they made this choice, + I have no idea. */ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int32_t b32; + +typedef float f32; +typedef double f64; + +#define ArrayCount(Array) (sizeof(Array)/sizeof((Array)[0])) + +#include "listing_0125_buffer.cpp" +#include "listing_0137_os_platform.cpp" +#include "listing_0109_pagefault_repetition_tester.cpp" + +typedef void ASMFunction(u64 Count, u8 *Data); + +extern "C" void Read_1x2(u64 Count, u8 *Data); +extern "C" void Read_8x2(u64 Count, u8 *Data); +#pragma comment (lib, "listing_0146_byte_read") + +struct test_function +{ + char const *Name; + ASMFunction *Func; +}; +test_function TestFunctions[] = +{ + {"Read_1x2", Read_1x2}, + {"Read_8x2", Read_8x2}, +}; + +int main(void) +{ + InitializeOSPlatform(); + + u64 RepeatCount = 1024*1024*1024ull; + buffer Buffer = AllocateBuffer(4096); + if(IsValid(Buffer)) + { + repetition_tester Testers[ArrayCount(TestFunctions)] = {}; + for(;;) + { + for(u32 FuncIndex = 0; FuncIndex < ArrayCount(TestFunctions); ++FuncIndex) + { + repetition_tester *Tester = &Testers[FuncIndex]; + test_function TestFunc = TestFunctions[FuncIndex]; + + printf("\n--- %s ---\n", TestFunc.Name); + NewTestWave(Tester, RepeatCount, GetCPUTimerFreq()); + + while(IsTesting(Tester)) + { + BeginTime(Tester); + TestFunc.Func(RepeatCount, Buffer.Data); + EndTime(Tester); + CountBytes(Tester, RepeatCount); + } + } + } + } + else + { + fprintf(stderr, "Unable to allocate memory buffer for testing"); + } + + FreeBuffer(&Buffer); + + return 0; +}