summaryrefslogtreecommitdiff
path: root/libmp/Plan9-386/mpvecdigmuladd.s
diff options
context:
space:
mode:
Diffstat (limited to 'libmp/Plan9-386/mpvecdigmuladd.s')
-rw-r--r--libmp/Plan9-386/mpvecdigmuladd.s52
1 files changed, 52 insertions, 0 deletions
diff --git a/libmp/Plan9-386/mpvecdigmuladd.s b/libmp/Plan9-386/mpvecdigmuladd.s
new file mode 100644
index 00000000..5a262ce8
--- /dev/null
+++ b/libmp/Plan9-386/mpvecdigmuladd.s
@@ -0,0 +1,52 @@
+/*
+ * 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 mpvecdigmuladd(SB),$0
+
+ MOVL b+0(FP),SI
+ MOVL n+4(FP),CX
+ MOVL m+8(FP),BX
+ MOVL p+12(FP),DI
+ MOVL CX,BP
+ NEGL BP /* BP = -n */
+ SHLL $2,CX
+ ADDL CX,SI /* SI = b + n */
+ ADDL CX,DI /* DI = p + n */
+ XORL CX,CX
+_muladdloop:
+ MOVL (SI)(BP*4),AX /* lo = b[i] */
+ MULL BX /* hi, lo = b[i] * m */
+ ADDL CX,AX /* lo += oldhi */
+ JCC _muladdnocarry1
+ INCL DX /* hi += carry */
+_muladdnocarry1:
+ ADDL AX,(DI)(BP*4) /* p[i] += lo */
+ JCC _muladdnocarry2
+ INCL DX /* hi += carry */
+_muladdnocarry2:
+ MOVL DX,CX /* oldhi = hi */
+ INCL BP /* i++ */
+ JNZ _muladdloop
+ XORL AX,AX
+ ADDL CX,(DI)(BP*4) /* p[n] + oldhi */
+ ADCL AX,AX /* return carry out of p[n] */
+ RET