Created
December 5, 2021 14:18
-
-
Save wheremyfoodat/c8f4d83d8e2e2c35788cdd2fc1ed71f0 to your computer and use it in GitHub Desktop.
Day 3 of AoC in aa64 (part 1 only)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
__attribute__ ((naked)) void asm_main() { | |
__asm__ volatile (R"( | |
// x19: Pointer to file | |
// x20: Bit cache (12 * 4 bytes of storage). Incremented on ones, decremented on zeroes. | |
// If the final result is > 0 then the most common value is 1, otherwise it's 0 | |
.equ NUM_BITS, 12 | |
part1: | |
stp x19, x30, [sp, -16]! // save return address and x19, lower stack | |
stp x20, x21, [sp, -16]! // Back up x20 and x21 for use too | |
stp x22, x23, [sp, -16]! // Same for x22 and x23 | |
sub x20, sp, NUM_BITS * 4 | |
sub sp, sp, NUM_BITS * 4 + 16 // Reserve some stack space for the bit cache | |
sub sp, sp, 4096 // Reserve 4096 bytes for strings | |
// Initialize bit cache to 0 | |
stp xzr, xzr, [x20] | |
stp xzr, xzr, [x20, 16] | |
stp xzr, xzr, [x20, 32] | |
adr x0, filename | |
adr x1, file_perms | |
bl fopen // x0 = file pointer | |
mov x19, x0 | |
loop: | |
bl feof // Check for eof as a sanity check | |
cbnz x0, end | |
mov x0, x19 | |
adr x1, input_fmt // Read entry | |
add x2, sp, 4096 | |
bl fscanf | |
add x0, sp, 4096 // x0 = address of bit string | |
mov x1, x20 // x1 = address of bit cache | |
mov x2, NUM_BITS // x2 = loop counter | |
bit_loop: | |
ldrb w3, [x0], 1 // Read bit of bit string | |
cmp w3, '1' // Check if the bit is 1 | |
ldr w3, [x1] // Load current bit cache value | |
beq is_one // Jump to is_one if the bit is 1 | |
sub w3, w3, 1 // Sub one from bit cache value if it is not 1 | |
str w3, [x1], 4 // Write back value, move to next bit | |
subs x2, x2, 1 // Decrement one from loop counter | |
bne bit_loop // Loop until x2 is 0 | |
done_with_number: | |
mov x0, x19 // x0 = file | |
b loop | |
end: | |
// Get our gamma value in x2 | |
mov x1, x20 | |
mov x2, NUM_BITS | |
bl number_from_bit_cache | |
rbit x0, x0 | |
lsr x0, x0, (64 - NUM_BITS) | |
mov x2, x0 | |
// x3 = epsilon value | |
eor x3, x0, 0xfff | |
adr x0, result1_fmt | |
mul x1, x2, x3 // x1 = gamma * epsilon | |
// print result | |
bl printf | |
part2: | |
// undo the mess we made | |
cleanup: | |
add sp, sp, 4096 | |
add sp, sp, 48 + 16 | |
ldp x22, x23, [sp], 16 | |
ldp x20, x21, [sp], 16 | |
ldp x19, x30, [sp], 16 | |
ret | |
is_one: | |
add w3, w3, 1 // Add one to bit cache value | |
str w3, [x1], 4 // Write back value, move to next bit | |
subs x2, x2, 1 // Decrement one from loop counter | |
bne bit_loop // Loop until x2 is 0 | |
b done_with_number // If x2 is 0 we're done with this number | |
// Params: | |
// x1 = pointer to bit cache | |
// x2 = number of bits to convert to a number (0 < x2 < 64) | |
// Return value in x0 (upper bits are 0) | |
// THE BITS ARE IN REVERSE ORDER. The callee needs to rbit+lsr the result as appropriate | |
number_from_bit_cache: | |
mov x0, 0 | |
mov x4, 0 // shift amount | |
number_from_bit_cache_loop: | |
ldr w5, [x1], 4 // Get bit cache entry | |
cmp w5, 0 // Check if it's > 0 | |
mov x6, 1 // x6 = x0 | (1 << shift amount) | |
lsl x6, x6, x4 | |
orr x6, x6, x0 | |
csel x0, x6, x0, gt // x0 = x6 if bit cache entry > 0 | |
add x4, x4, 1 // Increment shift amount by 1 | |
subs x2, x2, 1 // Decrement loop counter | |
bne number_from_bit_cache_loop | |
ret | |
filename: | |
.asciz "input.in" | |
file_perms: | |
.asciz "r" | |
input_fmt: | |
.asciz "%s\n" | |
result1_fmt: | |
.asciz "Result of part 1: %d\nGamma: %d Epsilon: %d\n" | |
)"); | |
} | |
int main() { | |
asm_main(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment