https://github.com/akkartik/mu/blob/main/apps/mandelbrot.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
15 var zero: float
16 var scene-cx/xmm1: float <- copy zero
17 var scene-cy/xmm2: float <- copy zero
18
19
20 var scene-width-scale: float
21 var dest/eax: (addr float) <- address scene-width-scale
22 fill-in-rational dest, 1, 2
23
24 var four: float
25 var dest/eax: (addr float) <- address four
26 fill-in-rational dest, 4, 1
27 var scene-width/xmm3: float <- copy four
28 {
29 mandelbrot screen scene-cx, scene-cy, scene-width
30
31 var adj/xmm0: float <- rational 2, 0x1c/28
32 adj <- multiply scene-width
33 scene-cx <- subtract adj
34 scene-cy <- add adj
35
36 scene-width <- multiply scene-width-scale
37 loop
38 }
39 }
40
41 fn mandelbrot screen: (addr screen), scene-cx: float, scene-cy: float, scene-width: float {
42 var a/eax: int <- copy 0
43 var b/ecx: int <- copy 0
44 a, b <- screen-size screen
45 var width/esi: int <- copy a
46 width <- shift-left 3/log2-font-width
47 var height/edi: int <- copy b
48 height <- shift-left 4/log2-font-height
49 var y/ecx: int <- copy 0
50 {
51 compare y, height
52 break-if->=
53 var imaginary/xmm1: float <- viewport-to-imaginary y, width, height, scene-cy, scene-width
54 var x/ebx: int <- copy 0
55 {
56 compare x, width
57 break-if->=
58 var real/xmm0: float <- viewport-to-real x, width, scene-cx, scene-width
59 var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max
60 iterations <- shift-right 3
61 var color/edx: int <- copy 0
62 iterations, color <- integer-divide iterations, 0x18/24/size-of-cycle-0
63 color <- add 0x20/cycle-0
64 pixel screen, x, y, color
65 x <- increment
66 loop
67 }
68 y <- increment
69 loop
70 }
71 }
72
73 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int {
74 var zero: float
75 var x/xmm0: float <- copy zero
76 var y/xmm1: float <- copy zero
77 var iterations/ecx: int <- copy 0
78 {
79 var done?/eax: boolean <- mandelbrot-done? x, y
80 compare done?, 0/false
81 break-if-!=
82 compare iterations, max
83 break-if->=
84 var newx/xmm2: float <- mandelbrot-x x, y, real
85 var newy/xmm3: float <- mandelbrot-y x, y, imaginary
86 x <- copy newx
87 y <- copy newy
88 iterations <- increment
89 loop
90 }
91 return iterations
92 }
93
94 fn mandelbrot-done? x: float, y: float -> _/eax: boolean {
95
96 var x2/xmm0: float <- copy x
97 x2 <- multiply x
98 var y2/xmm1: float <- copy y
99 y2 <- multiply y
100 var sum/xmm0: float <- copy x2
101 sum <- add y2
102 var four/eax: int <- copy 4
103 var four-f/xmm1: float <- convert four
104 compare sum, four-f
105 {
106 break-if-float>
107 return 0/false
108 }
109 return 1/true
110 }
111
112 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float {
113
114 var x2/xmm0: float <- copy x
115 x2 <- multiply x
116 var y2/xmm1: float <- copy y
117 y2 <- multiply y
118 var result/xmm0: float <- copy x2
119 result <- subtract y2
120 result <- add real
121 return result
122 }
123
124 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float {
125
126 var two/eax: int <- copy 2
127 var result/xmm0: float <- convert two
128 result <- multiply x
129 result <- multiply y
130 result <- add imaginary
131 return result
132 }
133
134
135
136
137
138 fn viewport-to-real x: int, width: int, scene-cx: float, scene-width: float -> _/xmm0: float {
139
140
141
142
143
144 var result/xmm0: float <- convert x
145 result <- multiply scene-width
146 var width-f/xmm1: float <- convert width
147 result <- divide width-f
148 result <- add scene-cx
149 var two/eax: int <- copy 2
150 var two-f/xmm2: float <- convert two
151 var half-scene-width/xmm1: float <- copy scene-width
152 half-scene-width <- divide two-f
153 result <- subtract half-scene-width
154 return result
155 }
156
157 fn viewport-to-imaginary y: int, width: int, height: int, scene-cy: float, scene-width: float -> _/xmm1: float {
158
159
160
161
162
163 var result/xmm0: float <- convert y
164 result <- multiply scene-width
165 var width-f/xmm1: float <- convert width
166 result <- divide width-f
167 result <- add scene-cy
168 var two/eax: int <- copy 2
169 var two-f/xmm2: float <- convert two
170 var second-term/xmm1: float <- copy scene-width
171 second-term <- divide two-f
172 var height-f/xmm2: float <- convert height
173 second-term <- multiply height-f
174 var width-f/xmm2: float <- convert width
175 second-term <- divide width-f
176 result <- subtract second-term
177 return result
178 }