Skip to content

Commit 7fd40bb

Browse files
committed
Refactorize RND label
1 parent 7c78ab9 commit 7fd40bb

4 files changed

Lines changed: 179 additions & 2 deletions

File tree

src/arch/zx48k/backend/runtime/random.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
class RandomLabels:
77
RANDOMIZE = f"{NAMESPACE}RANDOMIZE"
8+
RND = f"{NAMESPACE}RND"
89

910

1011
REQUIRED_MODULES = {
1112
RandomLabels.RANDOMIZE: 'random.asm',
13+
RandomLabels.RND: 'random.asm'
1214
}

src/arch/zx48k/translator.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,8 +1268,7 @@ def visit_ABS(self, node):
12681268
self.ic_abs(node.children[0].type_, node.t, node.children[0].t)
12691269

12701270
def visit_RND(self, node): # A special "ZEROARY" function with no parameters
1271-
self.ic_call('RND', Type.float_.size)
1272-
backend.REQUIRES.add('random.asm')
1271+
self.runtime_call(RuntimeLabel.RND, Type.float_.size)
12731272

12741273
def visit_PEEK(self, node):
12751274
self.ic_load(node.type_, node.t, '*' + str(node.children[0].t))

tests/functional/rnd.asm

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
org 32768
2+
__START_PROGRAM:
3+
di
4+
push ix
5+
push iy
6+
exx
7+
push hl
8+
exx
9+
ld hl, 0
10+
add hl, sp
11+
ld (__CALL_BACK__), hl
12+
ei
13+
jp __MAIN_PROGRAM__
14+
__CALL_BACK__:
15+
DEFW 0
16+
ZXBASIC_USER_DATA:
17+
; Defines USER DATA Length in bytes
18+
ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA
19+
.__LABEL__.ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_LEN
20+
.__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA
21+
_a:
22+
DEFB 00, 00, 00, 00, 00
23+
ZXBASIC_USER_DATA_END:
24+
__MAIN_PROGRAM__:
25+
ld de, 0
26+
ld hl, 0
27+
call RANDOMIZE
28+
call RND
29+
ld hl, _a
30+
call __STOREF
31+
ld hl, 0
32+
ld b, h
33+
ld c, l
34+
__END_PROGRAM:
35+
di
36+
ld hl, (__CALL_BACK__)
37+
ld sp, hl
38+
exx
39+
pop hl
40+
exx
41+
pop iy
42+
pop ix
43+
ei
44+
ret
45+
;; --- end of user code ---
46+
#line 1 "/zxbasic/src/arch/zx48k/library-asm/random.asm"
47+
; RANDOM functions
48+
RANDOMIZE:
49+
; Randomize with 32 bit seed in DE HL
50+
; if SEED = 0, calls ROM to take frames as seed
51+
PROC
52+
LOCAL TAKE_FRAMES
53+
LOCAL FRAMES
54+
ld a, h
55+
or l
56+
or d
57+
or e
58+
jr z, TAKE_FRAMES
59+
ld (RANDOM_SEED_LOW), hl
60+
ld (RANDOM_SEED_HIGH), de
61+
ret
62+
TAKE_FRAMES:
63+
; Takes the seed from frames
64+
ld hl, (FRAMES)
65+
ld (RANDOM_SEED_LOW), hl
66+
ld hl, (FRAMES + 2)
67+
ld (RANDOM_SEED_HIGH), hl
68+
ret
69+
FRAMES EQU 23672
70+
ENDP
71+
RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits
72+
RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits
73+
RAND:
74+
PROC
75+
LOCAL RAND_LOOP
76+
ld b, 4
77+
RAND_LOOP:
78+
ld hl,(RANDOM_SEED_LOW) ; xz -> yw
79+
ld de,0C0DEh ; yw -> zt
80+
ld (RANDOM_SEED_LOW),de ; x = y, z = w
81+
ld a,e ; w = w ^ ( w << 3 )
82+
add a,a
83+
add a,a
84+
add a,a
85+
xor e
86+
ld e,a
87+
ld a,h ; t = x ^ (x << 1)
88+
add a,a
89+
xor h
90+
ld d,a
91+
rra ; t = t ^ (t >> 1) ^ w
92+
xor d
93+
xor e
94+
ld d,l ; y = z
95+
ld e,a ; w = t
96+
ld (RANDOM_SEED_HIGH),de
97+
push af
98+
djnz RAND_LOOP
99+
pop de
100+
pop af
101+
ld e, a
102+
pop hl
103+
pop af
104+
ld l, a
105+
ret
106+
ENDP
107+
RND:
108+
; Returns a FLOATING point integer
109+
; using RAND as a mantissa
110+
PROC
111+
LOCAL RND_LOOP
112+
call RAND
113+
; BC = HL since ZX BASIC uses ED CB A registers for FP
114+
ld b, h
115+
ld c, l
116+
ld a, e
117+
or d
118+
or c
119+
or b
120+
ret z ; Returns 0 if BC=DE=0
121+
; We already have a random 32 bit mantissa in ED CB
122+
; From 0001h to FFFFh
123+
ld l, 81h ; Exponent
124+
; At this point we have [0 .. 1) FP number;
125+
; Now we must shift mantissa left until highest bit goes into carry
126+
ld a, e ; Use A register for rotating E faster (using RLA instead of RL E)
127+
RND_LOOP:
128+
dec l
129+
sla b
130+
rl c
131+
rl d
132+
rla
133+
jp nc, RND_LOOP
134+
; Now undo last mantissa left-shift once
135+
ccf ; Clears carry to insert a 0 bit back into mantissa -> positive FP number
136+
rra
137+
rr d
138+
rr c
139+
rr b
140+
ld e, a ; E must have the highest byte
141+
ld a, l ; exponent in A
142+
ret
143+
ENDP
144+
#line 23 "rnd.bas"
145+
#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm"
146+
__PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL)
147+
push de
148+
ex de, hl ; DE <- HL
149+
push ix
150+
pop hl ; HL <- IX
151+
add hl, de ; HL <- IX + HL
152+
pop de
153+
__ISTOREF: ; Load address at hl, and stores A,E,D,C,B registers at that address. Modifies A' register
154+
ex af, af'
155+
ld a, (hl)
156+
inc hl
157+
ld h, (hl)
158+
ld l, a ; HL = (HL)
159+
ex af, af'
160+
__STOREF: ; Stores the given FP number in A EDCB at address HL
161+
ld (hl), a
162+
inc hl
163+
ld (hl), e
164+
inc hl
165+
ld (hl), d
166+
inc hl
167+
ld (hl), c
168+
inc hl
169+
ld (hl), b
170+
ret
171+
#line 24 "rnd.bas"
172+
END

tests/functional/rnd.bas

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
RANDOMIZE
3+
a = RND
4+

0 commit comments

Comments
 (0)