https://github.com/akkartik/mu/blob/main/mandelbrot-fixed.mu
1
2
3
4
5
6
7
8
9
10
11
12
13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
14 mandelbrot screen
15 }
16
17
18
19
20 fn int-to-fixed in: int -> _/eax: int {
21 var result-f/eax: int <- copy in
22 result-f <- shift-left 8/fixed-precision
23 {
24 break-if-not-overflow
25 abort "int-to-fixed: overflow"
26 }
27 return result-f
28 }
29
30 fn fixed-to-int in-f: int -> _/eax: int {
31 var result/eax: int <- copy in-f
32 result <- shift-right-signed 8/fixed-precision
33 return result
34 }
35
36
37 fn test-fixed-conversion {
38
39 var f/eax: int <- int-to-fixed 0
40 var result/eax: int <- fixed-to-int f
41 check-ints-equal result, 0, "F - test-fixed-conversion - 0"
42
43 var f/eax: int <- int-to-fixed 1
44 var result/eax: int <- fixed-to-int f
45 check-ints-equal result, 1, "F - test-fixed-conversion - 1"
46
47 var f/eax: int <- int-to-fixed -1
48 var result/eax: int <- fixed-to-int f
49 check-ints-equal result, -1, "F - test-fixed-conversion - -1"
50
51 var f/eax: int <- int-to-fixed 1
52 f <- shift-right-signed 1
53 var result/eax: int <- fixed-to-int f
54 check-ints-equal result, 0, "F - test-fixed-conversion - 0.5"
55
56 var f/eax: int <- int-to-fixed -1
57 f <- shift-right-signed 1
58 var result/eax: int <- fixed-to-int f
59 check-ints-equal result, -1, "F - test-fixed-conversion - -0.5"
60
61 var f/eax: int <- int-to-fixed 3
62 f <- shift-right-signed 1
63 var result/eax: int <- fixed-to-int f
64 check-ints-equal result, 1, "F - test-fixed-conversion - 1.5"
65
66 var f/eax: int <- int-to-fixed -3
67 f <- shift-right-signed 1
68 var result/eax: int <- fixed-to-int f
69 check-ints-equal result, -2, "F - test-fixed-conversion - -1.5"
70
71 var f/eax: int <- int-to-fixed 5
72 f <- shift-right-signed 2
73 var result/eax: int <- fixed-to-int f
74 check-ints-equal result, 1, "F - test-fixed-conversion - 1.25"
75
76 var f/eax: int <- int-to-fixed -5
77 f <- shift-right-signed 2
78 var result/eax: int <- fixed-to-int f
79 check-ints-equal result, -2, "F - test-fixed-conversion - -1.25"
80 }
81
82
83
84 fn multiply-fixed a-f: int, b-f: int -> _/eax: int {
85 var result/eax: int <- copy a-f
86 result <- multiply b-f
87 {
88 break-if-not-overflow
89 abort "multiply-fixed: overflow"
90 }
91 result <- shift-right-signed 8/fixed-precision
92 return result
93 }
94
95 fn divide-fixed a-f: int, b-f: int -> _/eax: int {
96 var result-f/eax: int <- copy a-f
97 result-f <- shift-left 8/fixed-precision
98 {
99 break-if-not-overflow
100 abort "divide-fixed: overflow"
101 }
102 var dummy-remainder/edx: int <- copy 0
103 result-f, dummy-remainder <- integer-divide result-f, b-f
104 return result-f
105 }
106
107
108
109
110
111 fn mandelbrot screen: (addr screen) {
112 var a/eax: int <- copy 0
113 var b/ecx: int <- copy 0
114 a, b <- screen-size screen
115 var width/esi: int <- copy a
116 width <- shift-left 3/log2-font-width
117 var height/edi: int <- copy b
118 height <- shift-left 4/log2-font-height
119 var y/ecx: int <- copy 0
120 {
121 compare y, height
122 break-if->=
123 var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width, height
124 var x/eax: int <- copy 0
125 {
126 compare x, width
127 break-if->=
128 var real-f/edx: int <- viewport-to-real-f x, width
129 var iterations/esi: int <- mandelbrot-iterations-for-point real-f, imaginary-f, 0x400/max
130 compare iterations, 0x400/max
131 {
132 break-if->=
133 pixel screen, x, y, 0xf/white
134 }
135 compare iterations, 0x400/max
136 {
137 break-if-<
138 pixel screen, x, y, 0/black
139 }
140 x <- increment
141 loop
142 }
143 y <- increment
144 loop
145 }
146 }
147
148 fn mandelbrot-iterations-for-point real-f: int, imaginary-f: int, max: int -> _/esi: int {
149 var x-f/esi: int <- copy 0
150 var y-f/edi: int <- copy 0
151 var iterations/ecx: int <- copy 0
152 {
153 var done?/eax: boolean <- mandelbrot-done? x-f, y-f
154 compare done?, 0/false
155 break-if-!=
156 compare iterations, max
157 break-if->=
158 var x2-f/edx: int <- mandelbrot-x x-f, y-f, real-f
159 var y2-f/ebx: int <- mandelbrot-y x-f, y-f, imaginary-f
160 x-f <- copy x2-f
161 y-f <- copy y2-f
162 iterations <- increment
163 loop
164 }
165 return iterations
166 }
167
168 fn mandelbrot-done? x-f: int, y-f: int -> _/eax: boolean {
169
170 var tmp-f/eax: int <- multiply-fixed x-f, x-f
171 var result-f/ecx: int <- copy tmp-f
172 tmp-f <- multiply-fixed y-f, y-f
173 result-f <- add tmp-f
174 compare result-f, 0x400/4
175 {
176 break-if->
177 return 0/false
178 }
179 return 1/true
180 }
181
182 fn mandelbrot-x x-f: int, y-f: int, real-f: int -> _/edx: int {
183
184 var tmp-f/eax: int <- multiply-fixed x-f, x-f
185 var result-f/ecx: int <- copy tmp-f
186 tmp-f <- multiply-fixed y-f, y-f
187 result-f <- subtract tmp-f
188 result-f <- add real-f
189 return result-f
190 }
191
192 fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int {
193
194 var result-f/eax: int <- copy x-f
195 result-f <- shift-left 1/log2
196 result-f <- multiply-fixed result-f, y-f
197 result-f <- add imaginary-f
198 return result-f
199 }
200
201
202
203
204
205 fn viewport-to-real-f x: int, width: int -> _/edx: int {
206
207 var result-f/eax: int <- int-to-fixed x
208 var width-f/ecx: int <- copy width
209 width-f <- shift-left 8/fixed-precision
210 var half-width-f/edx: int <- copy width-f
211 half-width-f <- shift-right-signed 1/log2
212 result-f <- subtract half-width-f
213 result-f <- shift-left 2/log4
214 result-f <- divide-fixed result-f, width-f
215 return result-f
216 }
217
218 fn viewport-to-imaginary-f y: int, width: int, height: int -> _/ebx: int {
219
220 var result-f/eax: int <- int-to-fixed y
221 var half-height-f/ecx: int <- copy height
222 half-height-f <- shift-left 8/fixed-precision
223 half-height-f <- shift-right-signed 1/log2
224 result-f <- subtract half-height-f
225 result-f <- shift-left 2/log4
226 var width-f/ecx: int <- copy width
227 width-f <- shift-left 8/fixed-precision
228 result-f <- divide-fixed result-f, width-f
229 return result-f
230 }