Skip to content

Instantly share code, notes, and snippets.

@wheremyfoodat
Created December 5, 2021 14:18
Show Gist options
  • Save wheremyfoodat/c8f4d83d8e2e2c35788cdd2fc1ed71f0 to your computer and use it in GitHub Desktop.
Save wheremyfoodat/c8f4d83d8e2e2c35788cdd2fc1ed71f0 to your computer and use it in GitHub Desktop.
Day 3 of AoC in aa64 (part 1 only)
#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