diff --git a/html/mandelbrot-fixed.mu.html b/html/mandelbrot-fixed.mu.html index 3a09bf53..23fcdd66 100644 --- a/html/mandelbrot-fixed.mu.html +++ b/html/mandelbrot-fixed.mu.html @@ -59,223 +59,228 @@ if ('onhashchange' in window) {
   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 # The process of throwing bits away always adjusts a number towards -infinity.
- 32 fn test-fixed-conversion {
- 33   # 0
- 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   # 1
- 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   # -1
- 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   # 0.5 = 1/2
- 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   # -0.5 = -1/2
- 51   var f/eax: int <- int-to-fixed -1
+  3 # Install:
+  4 #   $ git clone https://github.com/akkartik/mu
+  5 #   $ cd mu
+  6 # Build on Linux:
+  7 #   $ ./translate mandelbrot-fixed.mu
+  8 # Build on other platforms (slow):
+  9 #   $ ./translate_emulated mandelbrot-fixed.mu
+ 10 # To run:
+ 11 #   $ qemu-system-i386 code.img
+ 12 
+ 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+ 14   mandelbrot screen
+ 15 }
+ 16 
+ 17 # Since they still look like int types, we'll append a '-f' suffix to variable
+ 18 # names to designate fixed-point numbers.
+ 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 # The process of throwing bits away always adjusts a number towards -infinity.
+ 37 fn test-fixed-conversion {
+ 38   # 0
+ 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   # 1
+ 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   # -1
+ 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   # 0.5 = 1/2
+ 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   # 1.5 = 3/2
- 56   var f/eax: int <- int-to-fixed 3
+ 53   var result/eax: int <- fixed-to-int f
+ 54   check-ints-equal result, 0, "F - test-fixed-conversion - 0.5"
+ 55   # -0.5 = -1/2
+ 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 - 1.5"
- 60   # -1.5 = -3/2
- 61   var f/eax: int <- int-to-fixed -3
+ 58   var result/eax: int <- fixed-to-int f
+ 59   check-ints-equal result, -1, "F - test-fixed-conversion - -0.5"
+ 60   # 1.5 = 3/2
+ 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   # 1.25 = 5/4
- 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   # -1.25 = -5/4
- 71   var f/eax: int <- int-to-fixed -5
+ 63   var result/eax: int <- fixed-to-int f
+ 64   check-ints-equal result, 1, "F - test-fixed-conversion - 1.5"
+ 65   # -1.5 = -3/2
+ 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   # 1.25 = 5/4
+ 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 # special routines for multiplying and dividing fixed-point numbers
- 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 # multiplying or dividing by an integer can use existing instructions.
-103 
-104 # adding and subtracting two fixed-point numbers can use existing instructions.
-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  # 3 + 8 = 11
-112   var height-f/edi: int <- copy b
-113   height-f <- shift-left 0xc/log2-font-height-and-fixed-precision  # 4 + 8 = 12
-114   var y/ecx: int <- copy 0
-115   {
-116     compare y, height-f
-117     break-if->=
-118     var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width-f, height-f
-119     var x/eax: int <- copy 0
-120     {
-121       compare x, width-f
-122       break-if->=
-123       var real-f/edx: int <- viewport-to-real-f x, width-f
-124       var iterations/esi: int <- mandelbrot-iterations-for-point real-f, imaginary-f, 0x400/max
-125       compare iterations, 0x400/max
-126       {
-127         break-if->=
-128         pixel screen, x, y, 0xf/white
-129       }
+ 73   var result/eax: int <- fixed-to-int f
+ 74   check-ints-equal result, 1, "F - test-fixed-conversion - 1.25"
+ 75   # -1.25 = -5/4
+ 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 # special routines for multiplying and dividing fixed-point numbers
+ 83 
+ 84 fn multiply-fixed a: int, b: int -> _/eax: int {
+ 85   var result/eax: int <- copy a
+ 86   result <- multiply b
+ 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 # multiplying or dividing by an integer can use existing instructions.
+108 
+109 # adding and subtracting two fixed-point numbers can use existing instructions.
+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-f/esi: int <- copy a
+116   width-f <- shift-left 0xb/log2-font-width-and-fixed-precision  # 3 + 8 = 11
+117   var height-f/edi: int <- copy b
+118   height-f <- shift-left 0xc/log2-font-height-and-fixed-precision  # 4 + 8 = 12
+119   var y/ecx: int <- copy 0
+120   {
+121     compare y, height-f
+122     break-if->=
+123     var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width-f, height-f
+124     var x/eax: int <- copy 0
+125     {
+126       compare x, width-f
+127       break-if->=
+128       var real-f/edx: int <- viewport-to-real-f x, width-f
+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, 0/black
+132         break-if->=
+133         pixel screen, x, y, 0xf/white
 134       }
-135       x <- increment
-136       loop
-137     }
-138     y <- increment
-139     loop
-140   }
-141 }
-142 
-143 fn mandelbrot-iterations-for-point real-f: int, imaginary-f: int, max: int -> _/esi: int {
-144   var x-f/esi: int <- copy 0
-145   var y-f/edi: int <- copy 0
-146   var iterations/ecx: int <- copy 0
-147   {
-148     var done?/eax: boolean <- mandelbrot-done? x-f, y-f
-149     compare done?, 0/false
-150     break-if-!=
-151     compare iterations, max
-152     break-if->=
-153     var x2-f/edx: int <- mandelbrot-x x-f, y-f, real-f
-154     var y2-f/ebx: int <- mandelbrot-y x-f, y-f, imaginary-f
-155     x-f <- copy x2-f
-156     y-f <- copy y2-f
-157     iterations <- increment
-158     loop
-159   }
-160   return iterations
-161 }
-162 
-163 fn mandelbrot-done? x-f: int, y-f: int -> _/eax: boolean {
-164   # x*x + y*y > 4
-165   var tmp-f/eax: int <- multiply-fixed x-f, x-f
-166   var result-f/ecx: int <- copy tmp-f
-167   tmp-f <- multiply-fixed y-f, y-f
-168   result-f <- add tmp-f
-169   compare result-f, 0x400/4
-170   {
-171     break-if->
-172     return 0/false
-173   }
-174   return 1/true
-175 }
-176 
-177 fn mandelbrot-x x-f: int, y-f: int, real-f: int -> _/edx: int {
-178   # x*x - y*y + real
-179   var tmp-f/eax: int <- multiply-fixed x-f, x-f
-180   var result-f/ecx: int <- copy tmp-f
-181   tmp-f <- multiply-fixed y-f, y-f
-182   result-f <- subtract tmp-f
-183   result-f <- add real-f
-184   return result-f
-185 }
-186 
-187 fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int {
-188   # 2*x*y + imaginary
-189   var result-f/eax: int <- copy x-f
-190   result-f <- shift-left 1/log2
-191   result-f <- multiply-fixed result-f, y-f
-192   result-f <- add imaginary-f
-193   return result-f
-194 }
-195 
-196 # Scale (x, y) pixel coordinates to a complex plane where the viewport width
-197 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
-198 # ratio.
-199 
-200 fn viewport-to-real-f x: int, width-f: int -> _/edx: int {
-201   # (x - width/2)*4/width
-202   var result-f/eax: int <- int-to-fixed x
-203   var half-width-f/ecx: int <- copy width-f
-204   half-width-f <- shift-right-signed 1/log2
-205   result-f <- subtract half-width-f
-206   result-f <- shift-left 2/log4
-207   result-f <- divide-fixed result-f, width-f
-208   return result-f
-209 }
-210 
-211 fn viewport-to-imaginary-f y: int, width-f: int, height-f: int -> _/ebx: int {
-212   # (y - height/2)*4/width
-213   var result-f/eax: int <- int-to-fixed y
-214   shift-right-signed height-f, 1/log2
-215   result-f <- subtract height-f
-216   result-f <- shift-left 2/log4
-217   result-f <- divide-fixed result-f, width-f
-218   return result-f
-219 }
+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   # x*x + y*y > 4
+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   # x*x - y*y + real
+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   # 2*x*y + imaginary
+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 # Scale (x, y) pixel coordinates to a complex plane where the viewport width
+202 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
+203 # ratio.
+204 
+205 fn viewport-to-real-f x: int, width-f: int -> _/edx: int {
+206   # (x - width/2)*4/width
+207   var result-f/eax: int <- int-to-fixed x
+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 viewport-to-imaginary-f y: int, width-f: int, height-f: int -> _/ebx: int {
+217   # (y - height/2)*4/width
+218   var result-f/eax: int <- int-to-fixed y
+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 }
 
diff --git a/html/mandelbrot.mu.html b/html/mandelbrot.mu.html index a70db941..5fa9d8e6 100644 --- a/html/mandelbrot.mu.html +++ b/html/mandelbrot.mu.html @@ -58,149 +58,154 @@ if ('onhashchange' in window) {
   1 # Mandelbrot set
   2 #
-  3 # To build:
-  4 #   $ ./translate mandelbrot.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 fn mandelbrot screen: (addr screen) {
- 13   var a/eax: int <- copy 0
- 14   var b/ecx: int <- copy 0
- 15   a, b <- screen-size screen
- 16   var width/esi: int <- copy a
- 17   width <- shift-left 3/log2-font-width
- 18   var height/edi: int <- copy b
- 19   height <- shift-left 4/log2-font-height
- 20   var y/ecx: int <- copy 0
- 21   {
- 22     compare y, height
- 23     break-if->=
- 24     var imaginary/xmm1: float <- viewport-to-imaginary y, width, height
- 25     var x/edx: int <- copy 0
- 26     {
- 27       compare x, width
- 28       break-if->=
- 29       var real/xmm0: float <- viewport-to-real x, width
- 30       var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max
- 31       compare iterations, 0x400/max
- 32       {
- 33         break-if->=
- 34         pixel screen, x, y, 0xf/white
- 35       }
+  3 # Install:
+  4 #   $ git clone https://github.com/akkartik/mu
+  5 #   $ cd mu
+  6 # Build on Linux:
+  7 #   $ ./translate mandelbrot.mu
+  8 # Build on other platforms (slow):
+  9 #   $ ./translate_emulated mandelbrot.mu
+ 10 # To run:
+ 11 #   $ qemu-system-i386 code.img
+ 12 
+ 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+ 14   mandelbrot screen
+ 15 }
+ 16 
+ 17 fn mandelbrot screen: (addr screen) {
+ 18   var a/eax: int <- copy 0
+ 19   var b/ecx: int <- copy 0
+ 20   a, b <- screen-size screen
+ 21   var width/esi: int <- copy a
+ 22   width <- shift-left 3/log2-font-width
+ 23   var height/edi: int <- copy b
+ 24   height <- shift-left 4/log2-font-height
+ 25   var y/ecx: int <- copy 0
+ 26   {
+ 27     compare y, height
+ 28     break-if->=
+ 29     var imaginary/xmm1: float <- viewport-to-imaginary y, width, height
+ 30     var x/edx: int <- copy 0
+ 31     {
+ 32       compare x, width
+ 33       break-if->=
+ 34       var real/xmm0: float <- viewport-to-real x, width
+ 35       var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max
  36       compare iterations, 0x400/max
  37       {
- 38         break-if-<
- 39         pixel screen, x, y, 0/black
+ 38         break-if->=
+ 39         pixel screen, x, y, 0xf/white
  40       }
- 41       x <- increment
- 42       loop
- 43     }
- 44     y <- increment
- 45     loop
- 46   }
- 47 }
- 48 
- 49 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int {
- 50   var zero: float
- 51   var x/xmm0: float <- copy zero
- 52   var y/xmm1: float <- copy zero
- 53   var iterations/ecx: int <- copy 0
- 54   {
- 55     var done?/eax: boolean <- mandelbrot-done? x, y
- 56     compare done?, 0/false
- 57     break-if-!=
- 58     compare iterations, max
- 59     break-if->=
- 60     var newx/xmm2: float <- mandelbrot-x x, y, real
- 61     var newy/xmm3: float <- mandelbrot-y x, y, imaginary
- 62     x <- copy newx
- 63     y <- copy newy
- 64     iterations <- increment
- 65     loop
- 66   }
- 67   return iterations
- 68 }
- 69 
- 70 fn mandelbrot-done? x: float, y: float -> _/eax: boolean {
- 71   # x*x + y*y > 4
- 72   var x2/xmm0: float <- copy x
- 73   x2 <- multiply x
- 74   var y2/xmm1: float <- copy y
- 75   y2 <- multiply y
- 76   var sum/xmm0: float <- copy x2
- 77   sum <- add y2
- 78   var four/eax: int <- copy 4
- 79   var four-f/xmm1: float <- convert four
- 80   compare sum, four-f
- 81   {
- 82     break-if-float>
- 83     return 0/false
- 84   }
- 85   return 1/true
- 86 }
- 87 
- 88 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float {
- 89   # x*x - y*y + real
- 90   var x2/xmm0: float <- copy x
- 91   x2 <- multiply x
- 92   var y2/xmm1: float <- copy y
- 93   y2 <- multiply y
- 94   var result/xmm0: float <- copy x2
- 95   result <- subtract y2
- 96   result <- add real
- 97   return result
- 98 }
- 99 
-100 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float {
-101   # 2*x*y + imaginary
-102   var two/eax: int <- copy 2
-103   var result/xmm0: float <- convert two
-104   result <- multiply x
-105   result <- multiply y
-106   result <- add imaginary
-107   return result
-108 }
-109 
-110 # Scale (x, y) pixel coordinates to a complex plane where the viewport width
-111 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
-112 # ratio.
-113 
-114 fn viewport-to-real x: int, width: int -> _/xmm0: float {
-115   # (x - width/2)*4/width
-116   var result/xmm0: float <- convert x
-117   var width-f/xmm1: float <- convert width
-118   var two/eax: int <- copy 2
-119   var two-f/xmm2: float <- convert two
-120   var half-width-f/xmm2: float <- reciprocal two-f
-121   half-width-f <- multiply width-f
-122   result <- subtract half-width-f
-123   var four/eax: int <- copy 4
-124   var four-f/xmm2: float <- convert four
-125   result <- multiply four-f
-126   result <- divide width-f
-127   return result
-128 }
-129 
-130 fn viewport-to-imaginary y: int, width: int, height: int -> _/xmm1: float {
-131   # (y - height/2)*4/width
-132   var result/xmm0: float <- convert y
-133   var height-f/xmm1: float <- convert height
-134   var half-height-f/xmm1: float <- copy height-f
-135   var two/eax: int <- copy 2
-136   var two-f/xmm2: float <- convert two
-137   half-height-f <- divide two-f
-138   result <- subtract half-height-f
-139   var four/eax: int <- copy 4
-140   var four-f/xmm1: float <- convert four
-141   result <- multiply four-f
-142   var width-f/xmm1: float <- convert width
-143   result <- divide width-f
-144   return result
-145 }
+ 41       compare iterations, 0x400/max
+ 42       {
+ 43         break-if-<
+ 44         pixel screen, x, y, 0/black
+ 45       }
+ 46       x <- increment
+ 47       loop
+ 48     }
+ 49     y <- increment
+ 50     loop
+ 51   }
+ 52 }
+ 53 
+ 54 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int {
+ 55   var zero: float
+ 56   var x/xmm0: float <- copy zero
+ 57   var y/xmm1: float <- copy zero
+ 58   var iterations/ecx: int <- copy 0
+ 59   {
+ 60     var done?/eax: boolean <- mandelbrot-done? x, y
+ 61     compare done?, 0/false
+ 62     break-if-!=
+ 63     compare iterations, max
+ 64     break-if->=
+ 65     var newx/xmm2: float <- mandelbrot-x x, y, real
+ 66     var newy/xmm3: float <- mandelbrot-y x, y, imaginary
+ 67     x <- copy newx
+ 68     y <- copy newy
+ 69     iterations <- increment
+ 70     loop
+ 71   }
+ 72   return iterations
+ 73 }
+ 74 
+ 75 fn mandelbrot-done? x: float, y: float -> _/eax: boolean {
+ 76   # x*x + y*y > 4
+ 77   var x2/xmm0: float <- copy x
+ 78   x2 <- multiply x
+ 79   var y2/xmm1: float <- copy y
+ 80   y2 <- multiply y
+ 81   var sum/xmm0: float <- copy x2
+ 82   sum <- add y2
+ 83   var four/eax: int <- copy 4
+ 84   var four-f/xmm1: float <- convert four
+ 85   compare sum, four-f
+ 86   {
+ 87     break-if-float>
+ 88     return 0/false
+ 89   }
+ 90   return 1/true
+ 91 }
+ 92 
+ 93 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float {
+ 94   # x*x - y*y + real
+ 95   var x2/xmm0: float <- copy x
+ 96   x2 <- multiply x
+ 97   var y2/xmm1: float <- copy y
+ 98   y2 <- multiply y
+ 99   var result/xmm0: float <- copy x2
+100   result <- subtract y2
+101   result <- add real
+102   return result
+103 }
+104 
+105 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float {
+106   # 2*x*y + imaginary
+107   var two/eax: int <- copy 2
+108   var result/xmm0: float <- convert two
+109   result <- multiply x
+110   result <- multiply y
+111   result <- add imaginary
+112   return result
+113 }
+114 
+115 # Scale (x, y) pixel coordinates to a complex plane where the viewport width
+116 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
+117 # ratio.
+118 
+119 fn viewport-to-real x: int, width: int -> _/xmm0: float {
+120   # (x - width/2)*4/width
+121   var result/xmm0: float <- convert x
+122   var width-f/xmm1: float <- convert width
+123   var two/eax: int <- copy 2
+124   var two-f/xmm2: float <- convert two
+125   var half-width-f/xmm2: float <- reciprocal two-f
+126   half-width-f <- multiply width-f
+127   result <- subtract half-width-f
+128   var four/eax: int <- copy 4
+129   var four-f/xmm2: float <- convert four
+130   result <- multiply four-f
+131   result <- divide width-f
+132   return result
+133 }
+134 
+135 fn viewport-to-imaginary y: int, width: int, height: int -> _/xmm1: float {
+136   # (y - height/2)*4/width
+137   var result/xmm0: float <- convert y
+138   var height-f/xmm1: float <- convert height
+139   var half-height-f/xmm1: float <- copy height-f
+140   var two/eax: int <- copy 2
+141   var two-f/xmm2: float <- convert two
+142   half-height-f <- divide two-f
+143   result <- subtract half-height-f
+144   var four/eax: int <- copy 4
+145   var four-f/xmm1: float <- convert four
+146   result <- multiply four-f
+147   var width-f/xmm1: float <- convert width
+148   result <- divide width-f
+149   return result
+150 }
 
diff --git a/mandelbrot-fixed.mu b/mandelbrot-fixed.mu index 59b61699..89fcad6f 100644 --- a/mandelbrot-fixed.mu +++ b/mandelbrot-fixed.mu @@ -1,7 +1,12 @@ # Mandelbrot set using fixed-point numbers. # -# To build: +# Install: +# $ git clone https://github.com/akkartik/mu +# $ cd mu +# Build on Linux: # $ ./translate mandelbrot-fixed.mu +# Build on other platforms (slow): +# $ ./translate_emulated mandelbrot-fixed.mu # To run: # $ qemu-system-i386 code.img diff --git a/mandelbrot.mu b/mandelbrot.mu index 84310a0d..01b86f2a 100644 --- a/mandelbrot.mu +++ b/mandelbrot.mu @@ -1,7 +1,12 @@ # Mandelbrot set # -# To build: +# Install: +# $ git clone https://github.com/akkartik/mu +# $ cd mu +# Build on Linux: # $ ./translate mandelbrot.mu +# Build on other platforms (slow): +# $ ./translate_emulated mandelbrot.mu # To run: # $ qemu-system-i386 code.img