⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rand16.asm

📁 CCS3.3自带的TI 5400系列DSP的dsplib文件。文档说明可以在TI公司网站上下载。
💻 ASM
字号:
;***********************************************************
; Version 2.20.01                                           
;***********************************************************
;****************************************************************
;  Filename:	rand16.asm
;  Description: computes vector of 16 bit random numbers
;----------------------------------------------------------------
;  Synopsis:
;
;  short oflag = rand16(DATA *r, ushort nr)
;                                                              
;  r[nx]	: pointer to output vector
;  nr           : number of vector elements to generate
;  oflag	: Overflow flag.  if oflag = 1 a 32-bit overflow had occured
;		  during the routine. This should be taken as a  warning not as
;		  error because it could due to intermediate overflows with
;		  no effect on the final result due to the C54x guard bits
;		  If oflag= 0 no 32-bit overflow has ocurred
;----------------------------------------------------------------
;  Description:
;		 This algorithm	is called the "Linear Congruential Method"
;		 introduced by D. Lehmer in 1951.  Many	random number
;		 generators exist, but this method is arguably the fastest
;		 for a 16-bit value.  If a 32-bit value	is needed, the code
;		 can be	modified by performing a 32-bit	multiply and using
;		 32-bit	constants (RNDMULT, RNDINC).  This method, however,
;		 does have one major disadvantage:  it is VERY sensitive to
;		 the values of RNDMULT and RNDINC.
;
;		 Much research has been	done to	identify the optimal choices
;		 of these constants to avoid degeneration.  The	constants used
;		 in the	subroutine below were chosen based on this research.
;		 Extreme care must be taken if changes to the original
;		 constants are made:
;
;		 M:  The modulus value.	 This routine returns a	random number
;		 -   from 0 to 65536 (64K) and is NOT internally bounded.  If
;		     the user needs a min/max limit, this must be coded
;		     externally	to this	routine.
;
;		 RNDSEED:  An arbitrary	constant.  Can be chosen to be any
;		 -------   value representable by the uP (0-64K).  If 0	(zero)
;			   is chosen, RNDINC should be some larger value than
;			   1.  Otherwise, the first two	values will be 0 and 1.
;			   This	is ok if the generator is given	three cycles
;			   to "warm up".  To change the	set of random numbers
;			   generated by	this routine, simply change the
;			   RNDSEED value.  RNDSEED=21845 is used in this
;			   routine because it is 65536/3.
;
;		 RNDMULT:  Should be chosen such that the last three digits
;		 -------   are even-2-1	(such as xx821,	x421, etc).
;			   RNDMULT=31821 is used in this routine.
;
;		 RNDINC:   In general, this constant can be any	prime number
;		 ------	   related to M	(or 64K	in this	case).	Two values
;			   were	actually tested:  1 and	13849.	Research
;			   shows that RNDINC (the increment value) should be
;			   chosen by the following formula:
;
;			   RNDINC = ((1/2 - (1/6 * SQRT(3))) * M)
;
;			   Using M=65536: RNDINC=13849 (as indicated above).
;			   RNDINC=1 was	also tested and	works fine.
;			   RNDINC=13849	is used	in this	routine.
;
;		 8-bit #:  If an 8-bit number is desired (0-255), the lower or
;		 -------   higher byte of the low accumulator can be used.
;			   However, the	"randomness" or	"uniqueness" of	each
;			   number is NOT guaranteed.  When choosing only 8
;			   bits	out of 16, duplications	might exist.
;			   Therefore, it is NOT	recommended to a portion of
;			   the 16-bit result to	implement scaling.  Scaling
;			   should be done mathematically external to this
;			   routine.
;
;		 CAUTION:  This	routine	can only be used for 16-bit values.
;		 -------   Do not use for 32-bit values	(upper half of ACC
;			   is not necessarily random because only the lower
;			   half	is saved from the previous result).  Do	NOT
;			   save	the result with	a shift	(e.g. SACL RndNum,1) -
;			   the algorithm immediately degenerates.
;
;
;----------------------------------------------------------------
; Algorithm
;	 
;		 rndnum(n) = ((rndnum(n-1) * RNDMULT) +	RNDINC)	MOD M
;
;		 where:		 M = modulus (set at 65536, i.e. 64K)
;				 n = 2 to ??? (number of random	#s generated)
;			 rndnum(1) = RNDSEED (arbitrary	constant)
;			 RNDMULT   = multiplier	(unique	constant)
;			 RNDINC	   = increment value (unique constant)
;----------------------------------------------------------------
;  Benchmarks
;
;  cycles	: 	16 + nx*4		(core)
;			10			(c-overhead)
;			core + c-overhead	(total)
;
;                        Note: Add one cycle overhead when in
;                              far mode
;
;  code size	:	28 words
;
;----------------------------------------------------------------
;  Revision History:
;         09/30/93 | Eric W. | Original draft.
;         01/03/96 | Alex T. | Optimized code.
;         09/01/97 | Jeff A. | Vectorized code.
;----------------------------------------------------------------

;----------------------------------------------------------------                  
; Include memory-mapped register mnemonics
;----------------------------------------------------------------

	.mmregs

;----------------------------------------------------------------
; Make adjustment for far-mode. Return address occupies an extra
; location when far-mode is active
;----------------------------------------------------------------

	.if __far_mode
OFFSET	.set 2
	.else
OFFSET	.set 1
	.endif

;----------------------------------------------------------------
; Define local stack variables
;----------------------------------------------------------------

	.asg	0, SP_RNDNUM
	.asg	1, SP_RNDMULT
	.asg	2, SP_RNDINC

;----------------------------------------------------------------
; Define size of local stack (number of words required for
; local variables
;----------------------------------------------------------------

	.asg	3, FRAME_SZ

;----------------------------------------------------------------
; Define offsets to command line arguments
;----------------------------------------------------------------

	.asg	OFFSET + FRAME_SZ, PARAM_OFFSET

	.asg	2 + PARAM_OFFSET, ARG_N

;----------------------------------------------------------------
; Assign register arguments
;----------------------------------------------------------------

	.asg	AR0, AR_Y
	
;----------------------------------------------------------------
; DEFINE CONSTANTS:
;----------------------------------------------------------------


RNDMULT	.set	31821		; Multiplier value
RNDINC	.set	13849		; Increment value

;----------------------------------------------------------------
;Generate Next Random Number:
;----------------------------------------------------------------

	
	.ref rndnum
	.def	_rand16
        .text

_rand16:
        PSHM    ST0                                 ; 1 cycle
        PSHM    ST1                                 ; 1 cycle
        RSBX    OVA                                 ; 1 cycle
        RSBX    OVB                                 ; 1 cycle

	frame #-FRAME_SZ			; 1 cycle                       
	rsbx	FRCT				; 1 cycle

;----------------------------------------------------------------
; Process command-line arguments
;----------------------------------------------------------------

	stlm	a, AR_Y				; 1 cycle
	ld	*sp(ARG_N), a			; 1 cycle
	sub	#1, a				; 1 cycle
	stlm	a, BRC				; 1 cycle


;----------------------------------------------------------------	
; These constants get stored on the stack to increase speed.
;----------------------------------------------------------------

	ld	*(rndnum), a			; 1 cycle
	stl	a, *sp(SP_RNDNUM)		; 1 cycle
	st	#RNDMULT, *sp(SP_RNDMULT)  	; 2 cycles
	st	#RNDINC, *sp(SP_RNDINC)		; 2 cycles

	ld 	*sp(SP_RNDNUM), t		; 1 cycle, TREG = previous rndnum

;---------------------------------------------------------------
; Create vector of random numbers
;---------------------------------------------------------------

LOOP_PROLOGUE:

        rptbd   LOOPEND-1			; 2 cycles
	ld	*(rndnum), a			; 1 cycle, delay slot
	stl	a, *sp(SP_RNDNUM)		; 1 cycle, delay slot

LOOPSTART:

	mpy	*sp(SP_RNDMULT), a 		; 1 cycle, ACC = rndnum * RNDMULT
	add	*sp(SP_RNDINC), a		; 1 cycle, ACC  = (rndnum * RNDMULT) + RNDINC
	stl 	a, *AR_Y 			; 1 cycle, Store result
	ld 	*AR_Y+, t 			; 1 cycle, TREG = previous rndnum
LOOPEND:


;---------------------------------------------------------------
; Return to calling program
;---------------------------------------------------------------

DONE:
	ld	#0, A				; 1 cycle
	xc	1, AOV				; 1 cycle
	ld	#1, A				; 1 cycle

	frame #FRAME_SZ				; 1 cycle
        POPM    ST1
        POPM    ST0

	.if __far_mode
	fretd					; 4 cycles
	.else
	retd					; 3 cycles
	.endif

;---------------------------------------------------------------
; Save last random number as seed for next 'rand'
;---------------------------------------------------------------

	st      t,*(rndnum) 			; 2 cycles, delay slot

;end of file. please do not remove. it is left here to ensure that no lines of code are removed by any editor


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -