tag:blogger.com,1999:blog-4757118446768919900.post6624764086038553843..comments2021-08-04T12:25:03.832-07:00Comments on Retro Programming: 16-Bit Xorshift Pseudorandom Numbers in Z80 AssemblyJohn Metcalfhttp://www.blogger.com/profile/09108374348083307900noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-4757118446768919900.post-76937951235579522342021-01-19T09:55:57.632-08:002021-01-19T09:55:57.632-08:00I see now after I've read this: https://codeba...I see now after I've read this: https://codebase64.org/doku.php?id=base:16bit_xorshift_random_generator - the code does x ^= x >> 9 and the low part of x ^= x << 7 in one step. False alarm :)bazehttps://www.blogger.com/profile/11640696340175010182noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-55920964526431258792021-01-19T09:36:07.299-08:002021-01-19T09:36:07.299-08:00I put this code in some programs I made to test RN...I put this code in some programs I made to test RNGs on my ti-84+ calculator (Z80). This versions fails pretty hard. John's version works very well (it even competes with a combined LCG+LFSR that has a much longer cycle length even though xorshift is in the same class as LFSRs). John's code is extraordinarily optimized which makes it a bit deceptive on how each instruction is contributing and the purpose of each bit.Zedahttps://www.blogger.com/profile/00169422726269584190noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-48417106558474057232021-01-19T05:40:08.737-08:002021-01-19T05:40:08.737-08:00Probably just a typo but there's redundant seq...Probably just a typo but there's redundant sequence of LD H,A + LD A,H :) They are already equal.bazehttps://www.blogger.com/profile/11640696340175010182noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-71374735291135544132021-01-19T05:22:01.001-08:002021-01-19T05:22:01.001-08:00Hi, I'm a bit late to the party but I don'...Hi, I'm a bit late to the party but I don't think the code does what it's supposed to do. I think the following sequence is meant to represent HL = HL ^ (HL << 7):<br /><br />ld a,h<br />rra<br />ld a,l<br />rra ; a = HLLLLLLL (but what about L0000000?)<br />xor h<br />ld h,a<br /><br />...but what about the lower byte which can still contain the lowest bit of L?bazehttps://www.blogger.com/profile/11640696340175010182noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-33408028213190105712020-04-01T08:39:35.828-07:002020-04-01T08:39:35.828-07:00The function is not correct, because the second XO...The function is not correct, because the second XOR is not correctly implemented.<br /><br />Shifting the contents of HL >> 9, can never result in using any of the bits of the 8 bit register L, since they would have been completely shifted out after 8 right shifts.<br /><br />So the second XOR snippet is incorrect.<br /><br />Instead of this:<br /><br /> ld a,l<br /> rra<br /> ld a,h<br /> rra<br /> xor l<br /><br />It should be:<br /><br /> ld a,h<br /> rra<br /> xor l<br /><br />NOTE: Since carry is already reset, by the previous XOR, no extra instruction required to set Carry bit to zero before the RRA instruction.<br /><br />And hence the complete (and shorter) function would become:<br /><br />xrnd:<br /> ld hl,1 ; seed must not be 0<br /><br /> ld a,h<br /> rra<br /> ld a,l<br /> rra<br /> xor h<br /> ld h,a<br /> ld a,h<br /> rra<br /> xor l<br /> ld l,a<br /> xor h<br /> ld h,a<br /><br /> ld (xrnd+1),hl<br /><br /> retRui Martinshttps://www.blogger.com/profile/17489743205431785079noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-25148865292977813442019-08-08T19:40:11.737-07:002019-08-08T19:40:11.737-07:00Thanks SO much for this. This is AWESOME!Thanks SO much for this. This is AWESOME!Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-67005046118213793662019-05-13T06:11:55.362-07:002019-05-13T06:11:55.362-07:00Great stuff! I ported this to C64, 30 cycles witho...Great stuff! I ported this to C64, 30 cycles without the RTS. I didn't need what is equivalent to the second lda a,l / rra because 6502 EOR does not touch carry:<br /><br />rng_zp_low = $02<br />rng_zp_high = $03<br /> ; seeding<br /> LDA #1 ; seed, can be anything except 0<br /> STA rng_zp_low<br /> LDA #0<br /> STA rng_zp_high<br /> ...<br />random <br />LDA rng_zp_high<br /> LSR<br /> LDA rng_zp_low<br /> ROR<br /> EOR rng_zp_high<br /> STA rng_zp_high ; high part of x ^= x << 7 done<br /> ROR ; A has now x >> 9 and high bit comes from low byte<br /> EOR rng_zp_low<br /> STA rng_zp_low ; x ^= x >> 9 and the low part of x ^= x << 7 done<br /> EOR rng_zp_high <br /> STA rng_zp_high ; x ^= x << 8 done<br /> RTSveikkohttps://www.blogger.com/profile/05633967627615672818noreply@blogger.comtag:blogger.com,1999:blog-4757118446768919900.post-88533860852852421862017-09-07T06:40:04.623-07:002017-09-07T06:40:04.623-07:00Oh my gosh, my new favorite site! I tried implemen...Oh my gosh, my new favorite site! I tried implementing this a while back with no luck. I did however find that combining a simple 16-bit LFSR and a 16-bit LCG works well. It's not as fast (148cc), but it does pass CACert labs' testing. Not sure how to post code boxes, but:<br /><br />prng16:<br />;collab with Runer112<br />;;Output:<br />;; HL is a pseudo-random int<br />;; A and BC are also, but much weaker and smaller cycles<br />;; Preserves DE<br />;;148cc, super fast<br />;;26 bytes<br />;;period length: 4,294,901,760<br />seed1=$+1<br /> ld hl,9999<br /> ld b,h<br /> ld c,l<br /> add hl,hl<br /> add hl,hl<br /> inc l<br /> add hl,bc<br /> ld (seed1),hl<br />seed2=$+1<br /> ld hl,987<br /> add hl,hl<br /> sbc a,a<br /> and 101101<br /> xor l<br /> ld l,a<br /> ld (seed2),hl<br /> add hl,bc<br /> retZedahttps://www.blogger.com/profile/16721586697747551289noreply@blogger.com