/**********************************************************************
*
* Big Integer Assembly Helpers
* Library for Microchip TCP/IP Stack
* - Accelerates processing for BigInt functions
*
**********************************************************************
* FileName: BigInt_helper_C32.S
* Dependencies: None
* Processor: PIC32
* Compiler: Microchip C32 v1.05 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright (C) 2002-2009 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product ("Device") which is
* integrated into Licensee's product; or
* (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
* ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
* used in conjunction with a Microchip ethernet controller for
* the sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Abhay Deshmukh 03/04/08 Original
*********************************************************************/
#define __GENERIC_TYPE_DEFS_H_
#define __COMPILER_H
#include "HardwareProfile.h"
#include "TCPIPConfig.h"
#if (defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_SSL_CLIENT)) && !defined(ENC100_INTERFACE_MODE)
#include "TCPIP Stack/regdef.h"
#define MAX_UNSIGNED_INT_VALUE 0xFFFFFFFF
#define ONE_VALUE 0x00000001
#define ZERO_VALUE 0x00000000
.bss
.align 4
.global _iA
.global _xA
.global _iB
.global _xB
.global _iR
.global _wC
_iA: .word 4 /* _iA, starting index for A (lower memory address, least significant byte/word) */
_xA: .word 4 /* _xA, end index for A (higher memory address, most significant byte/word) */
_iB: .word 4 /* _iB, starting index for B (lower memory address, least significant byte/word) */
_xB: .word 4 /* _xB, end index for B (higher memory address, most significant byte/word) */
_iR: .word 4 /* _iR, starting index for Res (lower memory address, least significant byte/word) */
_wC: .word 4 /* value of B for _mas (little endian word) */
.set noreorder
.text
/***************************************************************************
; Function: void _addBI()
;
; PreCondition: _iA and _iB are loaded with the address of the LSB of the BigInt
; _xA and _xB are loaded with the address of the MSB of the BigInt
; a.size >= b.magnitude
;
; Input: A and B, the BigInts to add
;
; Output: A = A + B
;
; Side Effects: None
;
; Overview: Quickly performs the bulk addition of two BigInts
;
; Note: Function works
;***************************************************************************/
/* Note :- There is no Carry/Borrow Flag in STATUS Register of PIC32...So Workarounds were done */
.global _addBI
.ent _addBI
_addBI:
la t0, _xA # Load adress of _xA
lw t0, 0(t0) # Load the Contents of memory pointing by t0 register
la t1, _iA
addiu t0, t0, 4 # Store the address present in _xA & increment it by 4 ( since every access is 32 bit )
lw t1, 0(t1) # Store the address present in __iA
la t2, _xB
lw t2, 0(t2)
la t3, _iB
addiu t2, t2, 4 # Store the address present in _xB & increment it by 4
lw t3, 0(t3) # Store the address present in _iB
la t6, ZERO_VALUE # Store 0x00000000 in t6
aDoAdd:
lw t4, 0(t3) # Place the LSW of _iB in t4
addiu t3, t3, 4 # t3 = t3 + t4
lw t5, 0(t1) # Place the LSW of _iA in t5
addu t5, t5, t6 # t5 = t5 + t6
addu t7, t5, t4 # t7 = t5 + t4
sw t7, 0(t1) # 4 bytes of data transfered from address specified by t1 to t5
sltu t8, t7, t5 # if ( t7 < t5 ) then ( t8 = 1 )
movz t8, t6, t5
move t6, t8 # PrevCarry = carry
bne t3, t2, aDoAdd # if t3 != t2 then Jump to 'aDoAdd'
addiu t1, t1, 4
beqz t6, addDone
nop
AddCarry:
beq t0, t1, addDone # if t0 = t1 then Jump to 'nextDoadd'
lw t7, 0(t1)
addiu t5, t7, 1
sw t5, 0(t1) # Store the Contents of t5 in memory pointed by t1 register
addiu t1, t1, 4
beqz t7, AddCarry
nop
addDone:
jr $ra # return to function from where you are called
nop
.end _addBI
/***************************************************************************
; Function: void _subBI()
;
; PreCondition: _iA and _iB are loaded with the address of the LSB of the BigInt
; _xA and _xB are loaded with the address of the MSB of the BigInt
;
; Input: A and B, the BigInts to subtract
;
; Output: A = A - B
;
; Side Effects: None
;
; Overview: Quickly performs the bulk subtraction of two BigInts
;
; Note: Function works
;***************************************************************************/
.global _subBI
.ent _subBI
_subBI:
la t0, _xA
lw t0, 0(t0) # Store the address present in __xA & increment it by 4
la t1, _iA # Store the address present in __iA
addiu t0, t0, 4
lw t1, 0(t1)
la t2, _xB # Store the address present in __xB & increment it by 4
lw t2, 0(t2)
la t3, _iB # Store the address present in __iB
addiu t2, t2, 4
lw t3, 0(t3)
la t6, ZERO_VALUE # Store 0x00000000 in t6
sDoSub:
move t8,$0
lw t4, 0(t3) # Place the LSW of __iB in t4
addiu t3, t3, 4 # t3 = t3 + t4
lw t5, 0(t1) # Place the LSW of __iA in t5
movz t8, t6, t5
subu t5, t5, t6 # t8 = t5 - t6
sltu t7, t5, t4 # if ( t8 < t4 ) then ( t7 = 1 )
subu t5, t5, t4 # t5 = t5 - t4
sw t5, 0(t1) # 4 bytes of data transfered from address specified by t1 to t5
or t7, t7, t8
move t6, t7
bne t3, t2, sDoSub
addiu t1, t1, 4
beqz t6, subDone
nop
SubBorrow:
beq t0, t1, subDone
lw t7, 0(t1)
addiu t5, t7, -1
sw t5, 0(t1)
addiu t1, t1, 4
beq t7,$0, SubBorrow
nop
subDone:
jr $ra
nop
.end _subBI
/***************************************************************************
; Function: void _zeroBI()
;
; PreCondition: _iA is loaded with the address of the LSB of the BigInt
; _xA is loaded with the address of the MSB of the BigInt
;
; Input: None
;
; Output: A = 0
;
; Side Effects: None
;
; Overview: Sets all words from _iA to _xA to zero
;
; Note: Function works
;***************************************************************************/
.global _zeroBI
.ent _zeroBI
_zeroBI:
la t0, _xA
lw t0, 0(t0) # Store the address present in __xA & increment it by 4
la t1, _iA # Store the address present in __iA
addiu t0, t0, 4
lw t1, 0(t1)
zDoZero:
sw $0, 0(t1) # The value of $0 register is always 0
addiu t1, t1, 4
bne t0, t1, zDoZero
nop
jr $ra
nop
.end _zeroBI
/***************************************************************************
; Function: void _msbBI()
;
; PreCondition: _iA is loaded with the address of the LSB of the BigInt buffer
; _xA is loaded with the address of the right most byte of the BigInt buffer
;
; Input: None
;
; Output: _xA is now pointing to the MSB of the BigInt
;
; Side Effects: None
;
; Overview: Finds the MSB (first non-zero word) of the BigInt, starting
; from the right-most word and testing to the left. This
; function will stop if _iA is reached.
;
; Note: Function works
;***************************************************************************/
.global _msbBI
.ent _msbBI
_msbBI:
la t2, _xA
lw t0, 0(t2) # Store the address present in __xA & increment it by 4
la t1, _iA # Store the address present in __iA
lw t1, 0(t1)
msbLoop:
lw t3, 0(t0)
bne t3, $0, msbDone
nop
addiu t0, t0, -4
bne t0, t1, msbLoop
nop
msbDone:
sw t0, 0(t2)
jr $ra
nop
.end _msbBI
/***************************************************************************
; Function: void _mulBI()
;
; PreCondition: _iA and _iB are loaded with the address of the LSB of each BigInt
; _xA and _xB are loaded with the address of the MSB of the BigInt
; _iR is loaded with the LSB address of the destination result memory
; _iR memory must be zeroed and have enough space (_xB-_iB+_xA-_iA words)
;
; Input: A and B, the BigInts to multiply
;
; Output: R = A * B
;
; Side Effects: None
;
; Overview: Performs the bulk multiplication of two BigInts
;
; Note: Function works. An Assumption has been made that 'R' is cleared to
; 'Zero' before calling this function.
;***************************************************************************/
.global _mulBI
.ent _mulBI
_mulBI:
la t0, _xA
lw t0, 0(t0) # Store the address present in _xA & increment it by 4
la t1, _iA # Store the address present in _iA
addiu t0, t0, 4
lw t1, 0(t1)
la t2, _xB # Store the address present in _xB & increment it by 4
lw t2, 0(t2)
la t3, _iB # Store the address present in _iB
addiu t2, t2, 4
lw t3, 0(t3)
la t4, _iR # Store the address present in _iR
lw t4, 0(t4)
la a0, ONE_VALUE # Store 0x00000001 in a0
addiu t6, $0, 0 # Store 0x0 in t6
mLoopB:
beq t3, t2, mDone
lw t7, 0(t3)
beq t7, $0, mContinue
addu t8, t4, t6
mthi $0 # Move 0 to HI Register.
addiu t5, t1, 0
mLoopA:
mfhi a1 # Store the contents from HI Register to 'a1' register
lw a3,0(t8)
addu a2, a1, a3
mtlo a2 # Move the contents from 'a1' register to LO register
sltu a1, a2, a1
bgtz a1, mHiPutOne
nop
b mMultAdd
mthi $0
mHiPutOne:
mthi a0 # Move the contents from 'a0' register to HI register
mMultAdd:
lw a1, 0(t5)
maddu a1, t7 # Multiply a1 with t7 then add with HI || LO register ( i.e HI || LO + a1 * t7 )
addiu t5, t5, 4
mflo a3 # Store the contents from LO Register to 'a3' register
sw a3,0(t8)
addiu t8, t8, 4
bne t5,t0, mLoopA
nop
mfhi a1 # Store the contents from HI Register to 'a1' register
sw a1, 0(t8) # Move the contents from 'a1' register to LO register
mContinue:
addiu t3, t3, 4
b mLoopB
addiu t6, t6, 4
mDone:
jr $ra
nop
.end _mulBI
/***************************************************************************
; Function: void _sqrBI()
;
; PreCondition: _iA is loaded with the address of the LSB of the BigInt
; _xA is loaded with the address of the MSB of the BigInt
; _iR is loaded with the LSB address of the destination result memory
; _iR memory must be zeroed and have enough space (_xB-_iB+_xA-_iA words)
;
; Input: A, the BigInt to square
;
; Output: R = A * A
;
; Side Effects: None
;
; Overview: Squares BigInt A and stores result in R
;
; Note: Function works
;***************************************************************************/
.global _sqrBI
.ent _sqrBI
_sqrBI:
la t0, _xA
lw t0, 0(t0) # Store the address present in _xA & increment it by 4
la t1, _xB # Store the address present in _xB & increment it by 4
sw t0, 0(t1)
la t0, _iA # Store the address present in _iA
lw t0, 0(t0)
la t1, _iB # Store the address present in _iB
b _mulBI
sw t0, 0(t1)
.end _sqrBI
/***************************************************************************
; Function: void _masBI()
;
; PreCondition: _iB is loaded with the LSB of the modulus BigInt
; _xB is loaded with the MSB of the modulus BigInt
; _wC is loaded with the 32 bit unsigned integer by which to multiply
; _iR is the starting LSB of the decumulator BigInt
.end __sqrBI
;
; Input: B (BigInt) and C (16-bit int) to multiply
;
; Output: R = R - (B * C)
;
; Side Effects: None
;
; Overview: Performs a Multiply And Subtract function. This is used in
; the modulus calculation to save several steps. A BigInt (iB/xB)
; is multiplied by a single word and subtracted rather than
; accumulated.
;
; Note: Decumulator is the opposite of an accumulator,
; if that wasn't obvious
;
; Note: Function works
;***************************************************************************/
.global _masBI
.ent _masBI
_masBI:
la t2, _xB # Store the address present in _xB & increment it by 4
lw t2, 0(t2)
la t3, _iB # Store the address present in _iB
addiu t2, t2, 4
lw t3, 0(t3)
la t1, _wC # Store the address present in _wC
lw t1, 0(t1)
la t4, _iR # Store the address present in _iR
lw t4, 0(t4)
la a1, ZERO_VALUE
subu t8, t2, t3
addiu t8, t8, 4
addiu t9, t4, 0
addiu a0, $0, 1
masLoop:
mthi $0
mfhi t6
mMultandSub:
mtlo t6
mthi $0
lw t5, 0(t3)
maddu t5, t1
nop
mflo t6
mCalc:
move a2, $0
lw t5, 0(t4)
movz a2, a1, t5
subu t5, t5, a1
sltu t7, t5, t6 # if ( t5 < t6 ) then ( t7 = 1 )
subu t5, t5, t6 # t5 = t5 - t6
sw t5, 0(t4) # 4 bytes of data transfered from address specified by t4 to t5
or t7, t7, a2
move a1, t7
addiu t4, t4, 4
addiu t3, t3, 4
bne t3, t2, mMultandSub
mfhi t6
move a2, $0
lw t5, 0(t4)
movz a2, a1, t5
subu t5, t5, a1
sltu t7, t5, t6 # if ( t5 < t6 ) then ( t7 = 1 )
subu t5, t5, t6 # t5 = t5 - t6
sw t5, 0(t4) # 4 bytes of data transfered from address specified by t4 to t5
or t7, t7, a2
move a1, t7
addiu t4, t4, 4
beqz a1, masDone
mSubBorrow:
subu t7, t4, t9
beq t7, t8, masDone
lw t7, 0(t4)
addiu t6, t7, -1
sw t6, 0(t4)
addiu t4, t4, 4
beq t7, $0, mSubBorrow
nop
masDone:
jr $ra
nop
.end _masBI
/***************************************************************************
; Function: void _copyBI()
;
; PreCondition: _iA and _iB are loaded with the address of the LSB of each BigInt
; _xA and _xB are loaded with the address of the MSB of each BigInt
;
; Input: A and B, the destination and source
;
; Output: A = B
;
; Side Effects: None
;
; Stack Req:
;
; Overview: Copies a value from one BigInt to another
;
; Note: Function works
;***************************************************************************/
.global _copyBI
.ent _copyBI
_copyBI:
la t0, _xA
lw t0, 0(t0) # Store the address present in __xA & increment it by 4
la t1, _iA # Store the address present in __iA
addiu t0, t0, 4
lw t1, 0(t1)
la t2, _xB # Store the address present in __xB & increment it by 4
lw t2, 0(t2)
la t3, _iB # Store the address present in __iB
addiu t2, t2, 4
lw t3, 0(t3)
cLoop:
lw t4, 0(t3)
sw t4, 0(t1)
addiu t3, t3, 4
beq t3, t2, cZeroLoopTest
addiu t1, t1, 4
bne t1,t0, cLoop
nop
jr $ra
nop
cZeroLoop:
sw $0, 0(t1)
addiu t1, t1, 4
cZeroLoopTest:
bne t1,t0, cZeroLoop
nop
cend:
jr $ra
nop
.end _copyBI
.set reorder
#endif
|