Compare commits
No commits in common. "ceb0a9488700f59b30ba6aefea5eeea1b63f50c8" and "0a1d4fbb2e538f895434e3bd51503f09915954de" have entirely different histories.
ceb0a94887
...
0a1d4fbb2e
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
-test
|
-test
|
||||||
test
|
test
|
||||||
main
|
main
|
||||||
*.o
|
|
||||||
100
collatz.S
100
collatz.S
@ -3,42 +3,9 @@
|
|||||||
# collatz problem
|
# collatz problem
|
||||||
|
|
||||||
.text
|
.text
|
||||||
# void collatz_len_and_peak(uint64_t x, uint64_t *steps, uint64_t *peak)
|
# void collatz_len_and_peek(uint64_t x, uint64_t *steps, uint64_t *peek)
|
||||||
.global collatz_len_and_peak
|
.global collatz_len_and_peek
|
||||||
.global scan_upto
|
collatz_len_and_peek:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# bu makrolar yukardaki belirlediğim stack'e çok bağlı yani %rbp relative
|
|
||||||
# bu demek oluyor ki stack değişirse bu makrolar da değişmek zorunda
|
|
||||||
# daha esnek bir tasarım offset eklemek olurdu
|
|
||||||
.macro save_registers base
|
|
||||||
movq %rax, -96(%\base)
|
|
||||||
movq %rcx, -88(%\base)
|
|
||||||
movq %rdx, -80(%\base)
|
|
||||||
movq %rsi, -72(%\base)
|
|
||||||
movq %rdi, -64(%\base)
|
|
||||||
movq %r8, -56(%\base)
|
|
||||||
movq %r9, -48(%\base)
|
|
||||||
movq %r10, -40(%\base)
|
|
||||||
movq %r11, -32(%\base)
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro restore_registers base
|
|
||||||
movq -96(%\base), %rax
|
|
||||||
movq -88(%\base), %rcx
|
|
||||||
movq -80(%\base), %rdx
|
|
||||||
movq -72(%\base), %rsi
|
|
||||||
movq -64(%\base), %rdi
|
|
||||||
movq -56(%\base), %r8
|
|
||||||
movq -48(%\base), %r9
|
|
||||||
movq -40(%\base), %r10
|
|
||||||
movq -32(%\base), %r11
|
|
||||||
.endm
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
collatz_len_and_peak:
|
|
||||||
# Collatz problem implementation
|
# Collatz problem implementation
|
||||||
# x -> rdi, steps -> rsi, peak -> rdx
|
# x -> rdi, steps -> rsi, peak -> rdx
|
||||||
|
|
||||||
@ -52,70 +19,17 @@ collatz_len_and_peak:
|
|||||||
testq $1, %r8 # 1 and n
|
testq $1, %r8 # 1 and n
|
||||||
jz .even
|
jz .even
|
||||||
# odd case
|
# odd case
|
||||||
leaq 1(%r8, %r8, 2), %r8 # n *= 3 -> lea ( base + index * scale )
|
leaq (%r8, %r8, 2), %r8 # n *= 3 -> lea base + index * scale
|
||||||
|
addq $1,%r8 # n += 1
|
||||||
jmp .next_step
|
jmp .next_step
|
||||||
.even:
|
.even:
|
||||||
shrq $1, %r8 # n /= 2
|
shrq $1, %r8 # n /= 2
|
||||||
.next_step:
|
.next_step:
|
||||||
cmpq (%rdx), %r8 # if (n > *peak) n - *peak
|
cmpq (%rdx), %r8 # if (n > *peek) n - *peek
|
||||||
jle .next
|
jle .next
|
||||||
movq %r8, (%rdx) # *peak = n
|
movq %r8, (%rdx) # *peek = n
|
||||||
.next:
|
.next:
|
||||||
addq $1, (%rsi) # (*steps)++
|
addq $1, (%rsi) # (*steps)++
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
# void scan_upto(uint64_t N, uint64_t *best_n, uint64_t *best_steps, uint64_t *best_peak, uint64_t *xor_steps)
|
|
||||||
scan_upto:
|
|
||||||
pushq %rbp
|
|
||||||
movq %rsp, %rbp
|
|
||||||
|
|
||||||
subq $104, %rsp # burda stack de local değişkenler tutulcak makro için 80 byte + 16 byte local değişkenler ama
|
|
||||||
# hizalamak da gerekiyor
|
|
||||||
|
|
||||||
# başlatma initialize
|
|
||||||
# rdi rsi rdx rcx r8
|
|
||||||
movq $1, (%rsi) # *best_n = 1
|
|
||||||
movq $0, (%rdx) # *best_steps = 0
|
|
||||||
movq $1, (%rcx) # *best_peak = 1
|
|
||||||
movq $0, (%r8) # *xor_steps = 0
|
|
||||||
|
|
||||||
movq $1, %r9 # n = 1
|
|
||||||
.loop_scan:
|
|
||||||
cmpq %rdi, %r9 # if (n <= N)
|
|
||||||
jg .done_scan
|
|
||||||
# local değişkenler
|
|
||||||
movq $0, -8(%rbp) # steps = 0
|
|
||||||
movq $0, -16(%rbp) # peak = 0
|
|
||||||
# şimdi fonksiyon çağırcam ama register sırasını korumam lazım bunlar
|
|
||||||
# caller-saved olduğu için diper fonksiyonda korunmazlar ve değişiler bu yüzden
|
|
||||||
# hali hazırda kullandığım registerları stack e vermem lazım
|
|
||||||
# ama bunu makro olarak yazmak istiyorum bir daha kullanmıycak olsamda
|
|
||||||
save_registers rbp
|
|
||||||
movq %r9, %rdi # n
|
|
||||||
leaq -8(%rbp), %rsi # steps
|
|
||||||
leaq -16(%rbp), %rdx # peak
|
|
||||||
call collatz_len_and_peak
|
|
||||||
restore_registers rbp
|
|
||||||
movq (%r8), %r11 # r11 = *xor_steps
|
|
||||||
xorq -8(%rbp), %r11 # *xor_steps ^= steps
|
|
||||||
movq %r11, (%r8) # *xor_steps = r11
|
|
||||||
movq (%rdx), %r11 # r11 = *best_steps
|
|
||||||
movq -8(%rbp), %r10 # r10 = steps
|
|
||||||
cmpq %r11, %r10 # if (steps > *best_steps)
|
|
||||||
jle .incr
|
|
||||||
movq %r9,(%rsi) # *best_n = n
|
|
||||||
movq %r10, (%rdx) # *best_steps = r10
|
|
||||||
movq -16(%rbp), %r11 # r11 = peak
|
|
||||||
movq %r11, (%rcx) # *best_peak = r11
|
|
||||||
|
|
||||||
.incr:
|
|
||||||
incq %r9
|
|
||||||
jmp .loop_scan
|
|
||||||
|
|
||||||
.done_scan:
|
|
||||||
leave
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|||||||
18
main.c
18
main.c
@ -1,21 +1,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void collatz_len_and_peak(uint64_t x, uint64_t *steps, uint64_t *peak);
|
void collatz_len_and_peek(uint64_t x, uint64_t *steps, uint64_t *peek);
|
||||||
void scan_upto(uint64_t N, uint64_t *best_n, uint64_t *best_steps, uint64_t *best_peak, uint64_t *xor_steps);
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("hello world!\n");
|
uint64_t steps, peak;
|
||||||
|
collatz_len_and_peek(13, &steps, &peak);
|
||||||
uint64_t N = 1000000;
|
printf("steps=%lu, peak=%lu\n", steps, peak);
|
||||||
uint64_t best_n, best_steps, best_peak, xor_steps;
|
|
||||||
scan_upto(N, &best_n, &best_steps, &best_peak, &xor_steps);
|
|
||||||
printf("collatz_longest(1..%lu)\n", N);
|
|
||||||
printf("n*=%lu\n", best_n);
|
|
||||||
printf("steps=%lu\n", best_steps);
|
|
||||||
printf("peak=%lu\n", best_peak);
|
|
||||||
printf("xor_steps=%lu\n", xor_steps);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user