aboutsummaryrefslogtreecommitdiff
path: root/src/libmp/386/mpvecdigmuladd-Darwin.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmp/386/mpvecdigmuladd-Darwin.s')
-rw-r--r--src/libmp/386/mpvecdigmuladd-Darwin.s69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/libmp/386/mpvecdigmuladd-Darwin.s b/src/libmp/386/mpvecdigmuladd-Darwin.s
new file mode 100644
index 00000000..c88dded1
--- /dev/null
+++ b/src/libmp/386/mpvecdigmuladd-Darwin.s
@@ -0,0 +1,69 @@
+/*
+ * mpvecdigmul(mpdigit *b, int n, mpdigit m, mpdigit *p)
+ *
+ * p += b*m
+ *
+ * each step look like:
+ * hi,lo = m*b[i]
+ * lo += oldhi + carry
+ * hi += carry
+ * p[i] += lo
+ * oldhi = hi
+ *
+ * the registers are:
+ * hi = DX - constrained by hardware
+ * lo = AX - constrained by hardware
+ * b+n = SI - can't be BP
+ * p+n = DI - can't be BP
+ * i-n = BP
+ * m = BX
+ * oldhi = CX
+ *
+ */
+.text
+
+.p2align 2,0x90
+.globl _mpvecdigmuladd
+_mpvecdigmuladd:
+ /* Prelude */
+ pushl %ebp /* save on stack */
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ leal 20(%esp), %ebp /* %ebp = FP for now */
+ movl 0(%ebp), %esi /* b */
+ movl 4(%ebp), %ecx /* n */
+ movl 8(%ebp), %ebx /* m */
+ movl 12(%ebp), %edi /* p */
+ movl %ecx, %ebp
+ negl %ebp /* BP = -n */
+ shll $2, %ecx
+ addl %ecx, %esi /* SI = b + n */
+ addl %ecx, %edi /* DI = p + n */
+ xorl %ecx, %ecx
+_muladdloop:
+ movl (%esi, %ebp, 4), %eax /* lo = b[i] */
+ mull %ebx /* hi, lo = b[i] * m */
+ addl %ecx,%eax /* lo += oldhi */
+ jae _muladdnocarry1
+ incl %edx /* hi += carry */
+_muladdnocarry1:
+ addl %eax, (%edi, %ebp, 4) /* p[i] += lo */
+ jae _muladdnocarry2
+ incl %edx /* hi += carry */
+_muladdnocarry2:
+ movl %edx, %ecx /* oldhi = hi */
+ incl %ebp /* i++ */
+ jnz _muladdloop
+ xorl %eax, %eax
+ addl %ecx, (%edi, %ebp, 4) /* p[n] + oldhi */
+ adcl %eax, %eax /* return carry out of p[n] */
+
+ /* Postlude */
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+