litwr wrote:
Thanks for this interesting code snippets.
Thank you for the response. Quite a bit of thought and time obviously went into it.
litwr wrote:
I have tried to make code for the TMS9900 a bit shorter.
Code:
xor @RNDM+3,r0 ; XOR r0 with random no.
clr R1 ; Put bit 28.XOR.31 in
sla R0,2 ; carry by shifting left
jnc RAND0
inc r1
RAND0 clr r2
a @RNDM,@RNDM ; rotate left
jnc RAND1
inc r2
RAND1 a r1,@RNDM
a @RNDM+2,@RNDM+2
a r2,@RNDM+2 ; The MSB is lost
My mistake was losing the context by including only a part of the code.
This is the full subroutine: it is the pseudo random number generator for the Space Voyage game on the 6800.
Code:
1045 F7 106B [5] 01975 RANDOM stab BSAVE ; Save the B accumulator
1048 C6 08 [2] 01976 ldab #8 ; Set counter
104A B6 106F [4] 01977 RPT ldaa RNDM+3 ; Get M.S. byte of random no.
104D 48 [2] 01978 asla ; Shift it left three
104E 48 [2] 01979 asla ; times to get bit 28
104F 48 [2] 01980 asla ; in line with bit 31
1050 B8 106F [4] 01981 eora RNDM+3 ; XOR A with random no.
1053 48 [2] 01982 asla ; Put bit 28.XOR.31 in
1054 48 [2] 01983 asla ; carry by shifting left
1055 79 106C [6] 01984 rol RNDM ; Rotate all four bytes of
1058 79 106D [6] 01985 rol RNDM+1 ; the random no., rotating
105B 79 106E [6] 01986 rol RNDM+2 ; the carry into the LSB
105E 79 106F [6] 01987 rol RNDM+3 ; The MSB is lost
1061 5A [2] 01988 decb ; Decrement the counter
1062 26 E6 (104A) [4] 01989 bne RPT ; If it's not 0, go repeat
1064 F6 106B [4] 01990 ldab BSAVE ; Restore the B accumulator
1067 B6 106C [4] 01991 ldaa RNDM ; Put random # in A
106A 39 [5] 01992 rts ; Return to calling program
For some reason, even though the 6800 is a big-endian, RNDM is stored in little-endian order. Ads in magazines indicate there was an 8080 version of Space Voyage but I have never found a copy of it anywhere. Perhaps this code originated on the little-endian 8080? The code can be rewritten to keep it in big-endian form, but that provides no advantage on the 6800.
Because of the endian mismatch, word-sized access to the two halves of RNDM by the 9900 will not work as is unless the order of the bytes is reversed. I did not do that, but it will be beneficial to cut the number of add with carry kludges from three down to one.
Code for the 9900 is deceptive. The "a @RNDM,@RNDM" instruction makes six 16-bit memory accesses: one to fetch the opcode, two to fetch the operand addresses as the processor is not aware they are the same, two to read the addends and one to write the sum. On the most common 9900 platform, the 99/4A, each 16-bit access suffers a four-cycle penalty as the memory circuitry makes two accesses to 8-bit memory.
litwr wrote:
I have also typed code for the Z80.
Code:
0100 3A 0126 [13] 00003 ld a,(RNDM+3)
0103 A9 [4] 00004 xor c ; XOR c with random no.
0104 17 [4] 00005 rla
0105 17 [4] 00006 rla
0106 21 0123 [10] 00007 ld hl,RNDM
0109 CB16 [15] 00008 rl (hl)
010B 23 [5] 00009 inc hl
010C CB16 [15] 00010 rl (hl)
010E 23 [5] 00011 inc hl
010F CB16 [15] 00012 rl (hl)
0111 23 [5] 00013 inc hl
0112 CB16 [15] 00014 rl (hl) ; The MSB is lost
I did not make a version for the Z80.
I did not do any optimizing as I wrote the code, but the 8080 version can also be made better by using the M pseudo register access left over as an artifact from the 8008:
Code:
0116 21 0128 [10] 00019 lxi H,RNDM
0119 7E [7] 00020 mov A,M
011A 17 [4] 00021 ral
011B 77 [7] 00022 mov M,A
011C 23 [5] 00023 inx H
011D 7E [7] 00024 mov A,M
011E 17 [4] 00025 ral
011F 77 [7] 00026 mov M,A
0120 23 [5] 00027 inx H
0121 7E [7] 00028 mov A,M
0122 17 [4] 00029 ral
0123 77 [7] 00030 mov M,A
0124 23 [5] 00031 inx H
0125 7E [7] 00032 mov A,M
0126 17 [4] 00033 ral
0127 77 [7] 00034 mov M,A
litwr wrote:
BTW you missed RNDM+3 in your 8080 snippet beginning.
This is the omitted part of the 8080 code; a copy of RNDM+3 is left in register C to do the xra:
Code:
143D 3A 1494 [13] 02086 RPT: lda RNDM+3 ; Get M.S. byte of random no.
1440 4F [5] 02087 mov C,A
1441 17 [4] 02088 ral ; Shift it left three
1442 17 [4] 02089 ral ; times to get bit 28
1443 17 [4] 02090 ral ; in line with bit 31
1444 A9 [4] 02091 xra C ; XOR A with random no.
1445 07 [4] 02092 rlc ; Put bit 28.XOR.31 in
1446 07 [4] 02093 rlc ; carry by shifting left
litwr wrote:
And, finally, my snippet for the 68000.
Code:
eor.b RNDM+3,d0 ; XOR c with random no.
lsl.b #2,d0
roxl RNDM
roxl RNDM+2
It is odd but all 68k can't shift/rotate double words in memory.
As stated above for the 9900, the 68000 cannot shift sixteen bits at a time unless the endian of RNDM is reversed. Then, a single 32-bit shift with roxl.l can be done.
Again, I have done no optimization and will not until all versions give the exact same result as the original 6800 code.