Inner step of multiplication in x64 assembly
authorSam Moore <matches@ucc.asn.au>
Sat, 5 Jul 2014 05:56:01 +0000 (13:56 +0800)
committerSam Moore <matches@ucc.asn.au>
Sat, 5 Jul 2014 05:56:01 +0000 (13:56 +0800)
Just does the multiplication of the array by one digit, taking into account overflows.
I hope. It's kind of difficult to test.

What I need is a VM with equivelant instruction set but magically uses decimals instead of binary 64 bit, so I can test with numbers
that my feeble human brain understands directly...

src/Makefile
src/mul_digits_asm.s [new file with mode: 0644]
src/tests/arb.cpp

index d92c969..9dfda08 100644 (file)
@@ -3,7 +3,7 @@ ARCH := $(shell uname -m)
 # TODO: stb_truetype doesn't compile with some of these warnings.
 CXX = g++ -std=gnu++0x -g -Wall -Werror -Wshadow -pedantic -rdynamic
 MAIN = main.o
-OBJ = log.o real.o bezier.o document.o objectrenderer.o view.o screen.o vfpu.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o add_digits_asm.o sub_digits_asm.o arbint.o
+OBJ = log.o real.o bezier.o document.o objectrenderer.o view.o screen.o vfpu.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o add_digits_asm.o sub_digits_asm.o mul_digits_asm.o arbint.o
 LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL
 LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL
 
diff --git a/src/mul_digits_asm.s b/src/mul_digits_asm.s
new file mode 100644 (file)
index 0000000..fb11765
--- /dev/null
@@ -0,0 +1,31 @@
+.section .text
+.globl mul_digits
+.type mul_digits, @function
+
+# Multiply an array of 64 bit digits by *one* 64 bit digit, modifies the array in place
+mul_digits:
+       movq %rdx, %rcx # rdx is reserved for mulq, use rcx as counter
+       movq $0, %r12 # Overflow register
+       loop:
+               movq %rsi, %rax # Value to multiply in %rax
+               mulq (%rdi) # Multiply, stored in %rdx:%rax (ie: we get TWO digits)
+               
+               # Add overflow from previous operation
+               add %r12, %rax
+               # Upper digit gets saved as next overflow
+               movq %rdx, %r12
+               
+               # Lower digit goes in current array position
+               movq %rax, (%rdi)
+               
+               dec %rcx # Decrement counter
+               jz end_loop # We are done
+               
+               # Move to next element in the array
+               leaq 8(,%rdi,1), %rdi
+               jmp loop # Repeat
+               
+       end_loop:
+       end:
+               movq %r12, %rax # Return overflow
+               ret # We are done
index c867a8f..354c337 100644 (file)
@@ -9,9 +9,17 @@ using namespace IPDF;
 
 int main(int argc, char ** argv)
 {
-       Arbint a(100L);
-       Arbint b(200L);
+       int64_t test[] = {12L, 5L};
+       test[1] = 0xE000000000000000;
+       int64_t size = sizeof(test)/sizeof(int64_t);
        
-       Arbint c(b-a);
-       printf("(%d), %s\n",c.Sign(), c.DigitStr().c_str());
+       int64_t mul = 2L;
+       
+       int64_t overflow = mul_digits(test, mul, size);
+       
+       for (int64_t i = 0; i < size; ++i)
+       {
+               printf("digit[%li] = %.16lx\n", i, test[i]);
+       }
+       printf("Overflow is %.16lx\n", overflow);
 }

UCC git Repository :: git.ucc.asn.au