Created
August 10, 2017 22:41
-
-
Save austinschwartz/f4d3adde0f2746a5c3677830b99e27ba to your computer and use it in GitHub Desktop.
64-bit tail-recursive multiply w/ two return registers
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
.section .data | |
.section .text | |
@ throughout the program | |
@ r4 stores m | |
@ r5 stores n | |
@ r6 stores the 32-bit LSB of acc (lower 32 bits) | |
@ r7 stores the 32-bit MSB of acc (higher 32 bits) | |
@ int multiply(int m, int n, int acc) { | |
@ if (m == 1) | |
@ return acc; | |
@ if (m < 0 && n < 0) | |
@ return multiply(-m, -n, -n); | |
@ if (m < 0) | |
@ return multiply(n, m, m); | |
@ return multiply(m - 1, n, n + acc); | |
@ } | |
@ | |
@ int mult_helper(int m, int n) { | |
@ return multiply(m, n, n); | |
@ } | |
.global multiply | |
multiply: | |
mov r4, r0 @ r4 = m | |
mov r5, r1 @ r5 = n | |
mov r6, #0 @ acc1 = 0 | |
mov r7, #0 @ acc0 = 0 | |
mov r9, #0 @ negative flag (if 1 then result is negative) | |
cmp r5, #0 | |
bge nispositive | |
b nisnegative | |
nispositive: | |
cmp r4, #0 | |
bge recurse @ both are positive, so go to recurse | |
mov r0, r5 @ (if m is negative, n is positive, | |
mov r1, r4 @ just swap the arguments and call multiply again | |
b multiply @ this ends up being less code) | |
nisnegative: | |
cmp r4, #0 | |
blt botharenegative | |
mov r9, #1 | |
neg r5, r5 | |
b recurse | |
botharenegative: | |
neg r5, r5 @ m = -m | |
neg r4, r4 @ n = -n | |
b recurse | |
recurse: | |
mov r3, r5 | |
sub r5, r3, #1 @ n = n - 1 | |
adds r6, r6, r4 @ add lower 32-bits | |
adc r7, r7, #0 @ add higher 32-bits (higher 32-bits of m is 0) | |
cmp r3, #1 | |
bgt recurse | |
cmp r9, #1 | |
@ doing 2s complement on our 64-bit integer | |
@ we would just do neg to make the result negative, | |
@ but we can't do that on a double-word | |
@ mvneq means do a bitwise not only if the cmp above sets the equal flag | |
mvneq r7, r7 | |
mvneq r6, r6 | |
addeq r6, r6, #1 | |
mov r1, r7 @ return acc1, acc0 | |
mov r0, r6 @ return acc1, acc0 | |
bx lr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment