📄 rand16.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 + -