// RANDOM Random Number Generator // Function RANDOM(LOW,HIGH) returns a pseudorandom // integer between LOW and HIGH. The random integer is // generated by a multiplier/adder method, with "MOD" used // to bring the integer into the range [LOW --> HIGH]. // Seed is initialized using the system time. MULT = 3141592653589793221 // Multiplier TEN6 = 1000000 // 1,000,000 (one million) .global booth, uint64_rem_min_lat, gettimeofday .data // Declare storage .align 8 // Desired alignment SEED: data8 0 // Seed for algorithm TIME: // For gettimeofday SECS: data8 0 // Seconds USEC: data8 0 // Microseconds VOID: data4 0 // (extra time zone) data4 0 // (info not needed) .text // Section for code .align 32 // Desired alignment .global random,random_ // These three lines .proc random,random_ // mark the mandatory random: // function entry random_: // FORTRAN needs underscore .prologue 12,r32 // Mask for rp, ar.pfs only alloc loc1 = ar.pfs,2,5,2,0 // ins, locals, outs .save rp,loc0 // Must save return address mov loc0 = b0 // to our caller .body // Now we really begin... first: add loc2 = @gprel(SEED),gp;; // loc2 -> SEED ld8 loc3 = [loc2];; // loc3 = SEED mov loc4 = gp // Save gp cmp.ne p6,p0 = 0,loc3 // First time called? (p6) br.cond.sptk.many gen // Not usually! add out0 = @gprel(TIME),gp // out0 -> TIME add out1 = @gprel(VOID),gp // out1 -> VOID br.call.sptk.many b0 = gettimeofday // System time mov gp = loc4;; // Restore gp add r2 = @gprel(SECS),gp;; // r2 -> SECS ld8 out0 = [r2] // SECS is multiplicand movl out1 = TEN6 // TEN6 is multiplier mov loc4 = r1 // Save gp br.call.sptk.many b0 = booth // r9,r8 = out0 * out1 mov gp = loc4;; // Restore gp add r2 = @gprel(USEC),gp;; // r2 -> USEC ld8 loc3 = [r2];; // USEC add loc3 = loc3,r8;; // Total microseconds gen: mov out0 = loc3 // SEED is multiplicand movl out1 = MULT // MULT is multiplier mov loc4 = gp // Save gp br.call.sptk.many b0 = booth // r9,r8 = out0 * out1 mov gp = loc4 // Restore gp add r8 = 1,r8;; // Product + 1 modulo 2^64 st8 [loc2] = r8 // Store as next seed mov out0 = r8 // RND sub out1 = in1,in0;; // HIGH - LOW add out1 = 1,out1 // RANGE mov loc4 = gp // Save gp br.call.sptk.many b0 = uint64_rem_min_lat // Modulo mov gp = loc4 // Restore gp add r8 = r8,in0 // LOW + (RND mod RANGE) done: mov b0 = loc0 // Restore return address mov ar.pfs = loc1 // Restore caller's ar.pfs br.ret.sptk.many b0;; // Back to caller .endp random // Mark end of procedure .include "uint64_rem_min_lat.s"