summaryrefslogtreecommitdiff
path: root/libmp/Plan9-amd64/mpvecdigmulsub.s
diff options
context:
space:
mode:
Diffstat (limited to 'libmp/Plan9-amd64/mpvecdigmulsub.s')
-rw-r--r--libmp/Plan9-amd64/mpvecdigmulsub.s54
1 files changed, 54 insertions, 0 deletions
diff --git a/libmp/Plan9-amd64/mpvecdigmulsub.s b/libmp/Plan9-amd64/mpvecdigmulsub.s
new file mode 100644
index 00000000..ea316431
--- /dev/null
+++ b/libmp/Plan9-amd64/mpvecdigmulsub.s
@@ -0,0 +1,54 @@
+/*
+ * mpvecdigmulsub(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 = SI - can't be BP
+ * p = DI - can't be BP
+ * i = BP
+ * n = CX - constrained by LOOP instr
+ * m = BX
+ * oldhi = EX
+ *
+ */
+TEXT mpvecdigmulsub(SB),$0
+
+/* MOVL b+0(FP),SI */
+ MOVQ RARG,SI
+ MOVL n+8(FP),CX
+ MOVL m+16(FP),BX
+ MOVQ p+24(FP),DI
+ XORL BP,BP
+ PUSHQ BP
+_mulsubloop:
+ MOVL (SI)(BP*4),AX /* lo = b[i] */
+ MULL BX /* hi, lo = b[i] * m */
+ ADDL 0(SP),AX /* lo += oldhi */
+ JCC _mulsubnocarry1
+ INCL DX /* hi += carry */
+_mulsubnocarry1:
+ SUBL AX,(DI)(BP*4)
+ JCC _mulsubnocarry2
+ INCL DX /* hi += carry */
+_mulsubnocarry2:
+ MOVL DX,0(SP)
+ INCL BP
+ LOOP _mulsubloop
+ POPQ AX
+ SUBL AX,(DI)(BP*4)
+ JCC _mulsubnocarry3
+ MOVQ $-1,AX
+ RET
+_mulsubnocarry3:
+ MOVQ $1,AX
+ RET