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