MandAzur/src/mandelbrot.s

74 lines
1.6 KiB
ArmAsm

/*
int mandelbrot(int32_t cr, int32_t ci, uint32_t t_squared, int steps);
(Pour moi : t_squared = (2 * 2) << 16, steps = 50)
Si renvoie 0 -> dans la fractale
Sinon renvoie un nombre entre 1...steps indiquant la "distance" (pour le dégradé)
*/
.global _mandelbrot
.text
/* Iteration of z = z²+c with threshold checks
@r4 Real part of c, cr
@r5 Imaginary part of c, ci
@r6 Squared threshold t²
@r7 Number of steps
If c is in the set, returns 0. Otherwise, returns the remaining number of
iterations to be checked before the process finised. */
_mandelbrot:
mov.l r8, @-r15
mov.l r9, @-r15
/* Start with z=z²=0 (z=x+iy) */
mov #0, r0
mov #0, r1
mov #0, r2
mov #0, r3
.loop:
/* Start xy */
dmuls.l r0, r1
/* Update x = x²-y²+cr */
mov r2, r0
sub r3, r0
add r4, r0
/* Get y = 2xy+ci while starting x²
TODO: Hope there's no overflow in that [shll r1]. It might be
TODO: provable because 2xy overflowing probably implies a lower
TODO: bound on x²+y² at the previous iteration. */
sts mach, r8
sts macl, r1
dmuls.l r0, r0
xtrct r8, r1
shll r1
add r5, r1
/* Get x² and keep the integer part at full precision for z²; at the
same time, start y² */
sts mach, r8
sts macl, r2
dmuls.l r1, r1
xtrct r8, r2
/* Get y² and compute ∥z∥² = x²+y² in 32:0 format */
sts mach, r9
sts macl, r3
add r9, r8
xtrct r9, r3
/* Compare ∥z∥² to t², return if the threshold is reached */
cmp/ge r6, r8
bt .end
/* Continue looping */
dt r7
bf .loop
.end:
mov.l @r15+, r9
mov.l @r15+, r8
rts
mov r7, r0