| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // +build !math_big_pure_go |
| |
| #include "textflag.h" |
| |
| // This file provides fast assembly versions for the elementary |
| // arithmetic operations on vectors implemented in arith.go. |
| |
| // func addVV(z, x, y []Word) (c Word) |
| TEXT ·addVV(SB),NOSPLIT,$0 |
| ADD.S $0, R0 // clear carry flag |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R4 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| ADD R4<<2, R1, R4 |
| B E1 |
| L1: |
| MOVW.P 4(R2), R5 |
| MOVW.P 4(R3), R6 |
| ADC.S R6, R5 |
| MOVW.P R5, 4(R1) |
| E1: |
| TEQ R1, R4 |
| BNE L1 |
| |
| MOVW $0, R0 |
| MOVW.CS $1, R0 |
| MOVW R0, c+36(FP) |
| RET |
| |
| |
| // func subVV(z, x, y []Word) (c Word) |
| // (same as addVV except for SBC instead of ADC and label names) |
| TEXT ·subVV(SB),NOSPLIT,$0 |
| SUB.S $0, R0 // clear borrow flag |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R4 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| ADD R4<<2, R1, R4 |
| B E2 |
| L2: |
| MOVW.P 4(R2), R5 |
| MOVW.P 4(R3), R6 |
| SBC.S R6, R5 |
| MOVW.P R5, 4(R1) |
| E2: |
| TEQ R1, R4 |
| BNE L2 |
| |
| MOVW $0, R0 |
| MOVW.CC $1, R0 |
| MOVW R0, c+36(FP) |
| RET |
| |
| |
| // func addVW(z, x []Word, y Word) (c Word) |
| TEXT ·addVW(SB),NOSPLIT,$0 |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R4 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| ADD R4<<2, R1, R4 |
| TEQ R1, R4 |
| BNE L3a |
| MOVW R3, c+28(FP) |
| RET |
| L3a: |
| MOVW.P 4(R2), R5 |
| ADD.S R3, R5 |
| MOVW.P R5, 4(R1) |
| B E3 |
| L3: |
| MOVW.P 4(R2), R5 |
| ADC.S $0, R5 |
| MOVW.P R5, 4(R1) |
| E3: |
| TEQ R1, R4 |
| BNE L3 |
| |
| MOVW $0, R0 |
| MOVW.CS $1, R0 |
| MOVW R0, c+28(FP) |
| RET |
| |
| |
| // func subVW(z, x []Word, y Word) (c Word) |
| TEXT ·subVW(SB),NOSPLIT,$0 |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R4 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| ADD R4<<2, R1, R4 |
| TEQ R1, R4 |
| BNE L4a |
| MOVW R3, c+28(FP) |
| RET |
| L4a: |
| MOVW.P 4(R2), R5 |
| SUB.S R3, R5 |
| MOVW.P R5, 4(R1) |
| B E4 |
| L4: |
| MOVW.P 4(R2), R5 |
| SBC.S $0, R5 |
| MOVW.P R5, 4(R1) |
| E4: |
| TEQ R1, R4 |
| BNE L4 |
| |
| MOVW $0, R0 |
| MOVW.CC $1, R0 |
| MOVW R0, c+28(FP) |
| RET |
| |
| |
| // func shlVU(z, x []Word, s uint) (c Word) |
| TEXT ·shlVU(SB),NOSPLIT,$0 |
| MOVW z_len+4(FP), R5 |
| TEQ $0, R5 |
| BEQ X7 |
| |
| MOVW z+0(FP), R1 |
| MOVW x+12(FP), R2 |
| ADD R5<<2, R2, R2 |
| ADD R5<<2, R1, R5 |
| MOVW s+24(FP), R3 |
| TEQ $0, R3 // shift 0 is special |
| BEQ Y7 |
| ADD $4, R1 // stop one word early |
| MOVW $32, R4 |
| SUB R3, R4 |
| MOVW $0, R7 |
| |
| MOVW.W -4(R2), R6 |
| MOVW R6<<R3, R7 |
| MOVW R6>>R4, R6 |
| MOVW R6, c+28(FP) |
| B E7 |
| |
| L7: |
| MOVW.W -4(R2), R6 |
| ORR R6>>R4, R7 |
| MOVW.W R7, -4(R5) |
| MOVW R6<<R3, R7 |
| E7: |
| TEQ R1, R5 |
| BNE L7 |
| |
| MOVW R7, -4(R5) |
| RET |
| |
| Y7: // copy loop, because shift 0 == shift 32 |
| MOVW.W -4(R2), R6 |
| MOVW.W R6, -4(R5) |
| TEQ R1, R5 |
| BNE Y7 |
| |
| X7: |
| MOVW $0, R1 |
| MOVW R1, c+28(FP) |
| RET |
| |
| |
| // func shrVU(z, x []Word, s uint) (c Word) |
| TEXT ·shrVU(SB),NOSPLIT,$0 |
| MOVW z_len+4(FP), R5 |
| TEQ $0, R5 |
| BEQ X6 |
| |
| MOVW z+0(FP), R1 |
| MOVW x+12(FP), R2 |
| ADD R5<<2, R1, R5 |
| MOVW s+24(FP), R3 |
| TEQ $0, R3 // shift 0 is special |
| BEQ Y6 |
| SUB $4, R5 // stop one word early |
| MOVW $32, R4 |
| SUB R3, R4 |
| MOVW $0, R7 |
| |
| // first word |
| MOVW.P 4(R2), R6 |
| MOVW R6>>R3, R7 |
| MOVW R6<<R4, R6 |
| MOVW R6, c+28(FP) |
| B E6 |
| |
| // word loop |
| L6: |
| MOVW.P 4(R2), R6 |
| ORR R6<<R4, R7 |
| MOVW.P R7, 4(R1) |
| MOVW R6>>R3, R7 |
| E6: |
| TEQ R1, R5 |
| BNE L6 |
| |
| MOVW R7, 0(R1) |
| RET |
| |
| Y6: // copy loop, because shift 0 == shift 32 |
| MOVW.P 4(R2), R6 |
| MOVW.P R6, 4(R1) |
| TEQ R1, R5 |
| BNE Y6 |
| |
| X6: |
| MOVW $0, R1 |
| MOVW R1, c+28(FP) |
| RET |
| |
| |
| // func mulAddVWW(z, x []Word, y, r Word) (c Word) |
| TEXT ·mulAddVWW(SB),NOSPLIT,$0 |
| MOVW $0, R0 |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R5 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| MOVW r+28(FP), R4 |
| ADD R5<<2, R1, R5 |
| B E8 |
| |
| // word loop |
| L8: |
| MOVW.P 4(R2), R6 |
| MULLU R6, R3, (R7, R6) |
| ADD.S R4, R6 |
| ADC R0, R7 |
| MOVW.P R6, 4(R1) |
| MOVW R7, R4 |
| E8: |
| TEQ R1, R5 |
| BNE L8 |
| |
| MOVW R4, c+32(FP) |
| RET |
| |
| |
| // func addMulVVW(z, x []Word, y Word) (c Word) |
| TEXT ·addMulVVW(SB),NOSPLIT,$0 |
| MOVW $0, R0 |
| MOVW z+0(FP), R1 |
| MOVW z_len+4(FP), R5 |
| MOVW x+12(FP), R2 |
| MOVW y+24(FP), R3 |
| ADD R5<<2, R1, R5 |
| MOVW $0, R4 |
| B E9 |
| |
| // word loop |
| L9: |
| MOVW.P 4(R2), R6 |
| MULLU R6, R3, (R7, R6) |
| ADD.S R4, R6 |
| ADC R0, R7 |
| MOVW 0(R1), R4 |
| ADD.S R4, R6 |
| ADC R0, R7 |
| MOVW.P R6, 4(R1) |
| MOVW R7, R4 |
| E9: |
| TEQ R1, R5 |
| BNE L9 |
| |
| MOVW R4, c+28(FP) |
| RET |
| |
| |
| // func divWVW(z* Word, xn Word, x []Word, y Word) (r Word) |
| TEXT ·divWVW(SB),NOSPLIT,$0 |
| // ARM has no multiword division, so use portable code. |
| B ·divWVW_g(SB) |
| |
| |
| // func divWW(x1, x0, y Word) (q, r Word) |
| TEXT ·divWW(SB),NOSPLIT,$0 |
| // ARM has no multiword division, so use portable code. |
| B ·divWW_g(SB) |
| |
| |
| // func mulWW(x, y Word) (z1, z0 Word) |
| TEXT ·mulWW(SB),NOSPLIT,$0 |
| MOVW x+0(FP), R1 |
| MOVW y+4(FP), R2 |
| MULLU R1, R2, (R4, R3) |
| MOVW R4, z1+8(FP) |
| MOVW R3, z0+12(FP) |
| RET |
| |
| // func bitLen(x Word) (n int) |
| TEXT ·bitLen(SB),NOSPLIT,$0 |
| MOVW x+0(FP), R0 |
| CLZ R0, R0 |
| RSB $32, R0 |
| MOVW R0, n+4(FP) |
| RET |