From 46f7e4fff395325fd333b01cc780ce231741bceb Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 8 May 2021 23:53:28 -0700 Subject: . --- html/mandelbrot-fixed.mu.html | 287 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 html/mandelbrot-fixed.mu.html (limited to 'html/mandelbrot-fixed.mu.html') diff --git a/html/mandelbrot-fixed.mu.html b/html/mandelbrot-fixed.mu.html new file mode 100644 index 00000000..318a7525 --- /dev/null +++ b/html/mandelbrot-fixed.mu.html @@ -0,0 +1,287 @@ + + + + +Mu - mandelbrot-fixed.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/mandelbrot-fixed.mu +
+  1 # Mandelbrot set using fixed-point numbers.
+  2 #
+  3 # To build:
+  4 #   $ ./translate mandelbrot-fixed.mu
+  5 # To run:
+  6 #   $ qemu-system-i386 code.img
+  7 
+  8 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+  9   mandelbrot screen
+ 10 }
+ 11 
+ 12 # Since they still look like int types, we'll append a '-f' suffix to variable
+ 13 # names to designate fixed-point numbers.
+ 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 fn test-fixed-conversion {
+ 32   # 0
+ 33   var f/eax: int <- int-to-fixed 0
+ 34   var result/eax: int <- fixed-to-int f
+ 35   check-ints-equal result, 0, "F - test-fixed-conversion - 0"
+ 36   # 1
+ 37   var f/eax: int <- int-to-fixed 1
+ 38   var result/eax: int <- fixed-to-int f
+ 39   check-ints-equal result, 1, "F - test-fixed-conversion - 1"
+ 40   # -1
+ 41   var f/eax: int <- int-to-fixed -1
+ 42   var result/eax: int <- fixed-to-int f
+ 43   check-ints-equal result, -1, "F - test-fixed-conversion - -1"
+ 44   # 0.5 = 1/2
+ 45   var f/eax: int <- int-to-fixed 1
+ 46   f <- shift-right-signed 1
+ 47   var result/eax: int <- fixed-to-int f
+ 48   check-ints-equal result, 0, "F - test-fixed-conversion - 0.5"
+ 49   # -0.5 = -1/2
+ 50   var f/eax: int <- int-to-fixed -1
+ 51   f <- shift-right-signed 1
+ 52   var result/eax: int <- fixed-to-int f
+ 53   check-ints-equal result, -1, "F - test-fixed-conversion - -0.5"
+ 54   # 1.5 = 3/2
+ 55   var f/eax: int <- int-to-fixed 3
+ 56   f <- shift-right-signed 1
+ 57   var result/eax: int <- fixed-to-int f
+ 58   check-ints-equal result, 1, "F - test-fixed-conversion - 1.5"
+ 59   # -1.5 = -3/2
+ 60   var f/eax: int <- int-to-fixed -3
+ 61   f <- shift-right-signed 1
+ 62   var result/eax: int <- fixed-to-int f
+ 63   check-ints-equal result, -2, "F - test-fixed-conversion - -1.5"
+ 64   # 1.25 = 5/4
+ 65   var f/eax: int <- int-to-fixed 5
+ 66   f <- shift-right-signed 2
+ 67   var result/eax: int <- fixed-to-int f
+ 68   check-ints-equal result, 1, "F - test-fixed-conversion - 1.25"
+ 69   # -1.25 = -5/4
+ 70   var f/eax: int <- int-to-fixed -5
+ 71   f <- shift-right-signed 2
+ 72   var result/eax: int <- fixed-to-int f
+ 73   check-ints-equal result, -2, "F - test-fixed-conversion - -1.25"
+ 74 }
+ 75 
+ 76 # special routines for multiplying and dividing fixed-point numbers
+ 77 
+ 78 fn multiply-fixed a: int, b: int -> _/eax: int {
+ 79   var result/eax: int <- copy a
+ 80   result <- multiply b
+ 81   {
+ 82     break-if-not-overflow
+ 83     abort "multiply-fixed: overflow"
+ 84   }
+ 85   result <- shift-right-signed 8/fixed-precision
+ 86   return result
+ 87 }
+ 88 
+ 89 fn divide-fixed a-f: int, b-f: int -> _/eax: int {
+ 90   var result-f/eax: int <- copy a-f
+ 91   result-f <- shift-left 8/fixed-precision
+ 92   {
+ 93     break-if-not-overflow
+ 94     abort "divide-fixed: overflow"
+ 95   }
+ 96   var dummy-remainder/edx: int <- copy 0
+ 97   result-f, dummy-remainder <- integer-divide result-f, b-f
+ 98   return result-f
+ 99 }
+100 
+101 # multiplying or dividing by an integer can use existing instructions.
+102 
+103 # adding and subtracting two fixed-point numbers can use existing instructions.
+104 
+105 fn mandelbrot screen: (addr screen) {
+106   var a/eax: int <- copy 0
+107   var b/ecx: int <- copy 0
+108   a, b <- screen-size screen
+109   var width-f/esi: int <- copy a
+110   width-f <- shift-left 0xb/log2-font-width-and-fixed-precision  # 3 + 8 = 11
+111   var height-f/edi: int <- copy b
+112   height-f <- shift-left 0xc/log2-font-height-and-fixed-precision  # 4 + 8 = 12
+113   # it might make sense to keep x and y as regular ints
+114   # treating them as fixed-point for demonstration purposes
+115   var y-f/ecx: int <- copy 0
+116   {
+117     compare y-f, height-f
+118     break-if->=
+119     var imaginary-f/ebx: int <- mandelbrot-min-y y-f, width-f, height-f
+120     var x-f/eax: int <- copy 0
+121     {
+122       compare x-f, width-f
+123       break-if->=
+124       var real-f/edx: int <- mandelbrot-min-x x-f, width-f
+125       var iterations/esi: int <- mandelbrot-pixel real-f, imaginary-f, 0x400/max
+126       {
+127         var x: int
+128         var y: int
+129         var tmp/eax: int <- fixed-to-int x-f
+130         copy-to x, tmp
+131         tmp <- fixed-to-int y-f
+132         copy-to y, tmp
+133         compare iterations, 0x400/max
+134         {
+135           break-if->=
+136           pixel screen, x, y, 0xf/white
+137         }
+138         compare iterations, 0x400/max
+139         {
+140           break-if-<
+141           pixel screen, x, y, 0/black
+142         }
+143       }
+144       x-f <- add 0x100/1
+145       loop
+146     }
+147     y-f <- add 0x100/1
+148     loop
+149   }
+150 }
+151 
+152 fn mandelbrot-pixel real-f: int, imaginary-f: int, max: int -> _/esi: int {
+153   var x-f/esi: int <- copy 0
+154   var y-f/edi: int <- copy 0
+155   var iterations/ecx: int <- copy 0
+156   {
+157     var done?/eax: boolean <- mandelbrot-done? x-f, y-f
+158     compare done?, 0/false
+159     break-if-!=
+160     compare iterations, max
+161     break-if->=
+162     var x2-f/edx: int <- mandelbrot-x x-f, y-f, real-f
+163     var y2-f/ebx: int <- mandelbrot-y x-f, y-f, imaginary-f
+164     x-f <- copy x2-f
+165     y-f <- copy y2-f
+166     iterations <- increment
+167     loop
+168   }
+169   return iterations
+170 }
+171 
+172 fn mandelbrot-done? x-f: int, y-f: int -> _/eax: boolean {
+173   # x*x + y*y > 4
+174   var tmp-f/eax: int <- multiply-fixed x-f, x-f
+175   var result-f/ecx: int <- copy tmp-f
+176   tmp-f <- multiply-fixed y-f, y-f
+177   result-f <- add tmp-f
+178   compare result-f, 0x400/4
+179   {
+180     break-if->
+181     return 0/false
+182   }
+183   return 1/true
+184 }
+185 
+186 fn mandelbrot-x x-f: int, y-f: int, real-f: int -> _/edx: int {
+187   # x*x - y*y + real
+188   var tmp-f/eax: int <- multiply-fixed x-f, x-f
+189   var result-f/ecx: int <- copy tmp-f
+190   tmp-f <- multiply-fixed y-f, y-f
+191   result-f <- subtract tmp-f
+192   result-f <- add real-f
+193   return result-f
+194 }
+195 
+196 fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int {
+197   # 2*x*y + imaginary
+198   var result-f/eax: int <- copy x-f
+199   result-f <- shift-left 1/log2
+200   result-f <- multiply-fixed result-f, y-f
+201   result-f <- add imaginary-f
+202   return result-f
+203 }
+204 
+205 fn mandelbrot-min-x x-f: int, width-f: int -> _/edx: int {
+206   # (x - width/2)*4/width
+207   var result-f/eax: int <- copy x-f
+208   var half-width-f/ecx: int <- copy width-f
+209   half-width-f <- shift-right-signed 1/log2
+210   result-f <- subtract half-width-f
+211   result-f <- shift-left 2/log4
+212   result-f <- divide-fixed result-f, width-f
+213   return result-f
+214 }
+215 
+216 fn mandelbrot-min-y y-f: int, width-f: int, height-f: int -> _/ebx: int {
+217   # (y - height/2)*4/width
+218   var result-f/eax: int <- copy y-f
+219   shift-right-signed height-f, 1/log2
+220   result-f <- subtract height-f
+221   result-f <- shift-left 2/log4
+222   result-f <- divide-fixed result-f, width-f
+223   return result-f
+224 }
+
+ + + -- cgit 1.4.1-2-gfad0