about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-11-27 13:24:50 -0800
committerKartik Agaram <vc@akkartik.com>2020-11-27 21:37:20 -0800
commit6f65b65f7d7261d79b58df25e5e0b20bfbc240ec (patch)
tree02197d3c76d993cf61ff0c2a5ff2bf7e016462b3
parent704265bd3c805ea71c0a0bc8a4280de46976b126 (diff)
downloadmu-6f65b65f7d7261d79b58df25e5e0b20bfbc240ec.tar.gz
7290
I've wrestled for a long time with how to support integer division with
its hard-coded registers. The answer's always been staring me in the face:
just turn it into a function! We already expect function outputs to go
to hard-coded registers.
-rw-r--r--314divide.subx17
-rw-r--r--400.mu2
-rw-r--r--406int32.mu101
-rw-r--r--apps/tile/value.mu6
4 files changed, 23 insertions, 103 deletions
diff --git a/314divide.subx b/314divide.subx
new file mode 100644
index 00000000..c0b85526
--- /dev/null
+++ b/314divide.subx
@@ -0,0 +1,17 @@
+== code
+
+integer-divide:  # a: int, b: int -> quotient/eax: int, remainder/edx: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # eax = a
+    8b/-> *(ebp+8) 0/r32/eax
+    # edx = all 0s or all 1s
+    99/sign-extend-eax-into-edx
+    # quotient, remainder = divide eax by b
+    f7 7/subop/divide-eax-edx-by *(ebp+0xc)
+$integer-divide:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
diff --git a/400.mu b/400.mu
index 4f95c226..d3ff0e9b 100644
--- a/400.mu
+++ b/400.mu
@@ -185,3 +185,5 @@ sig stream-final s: (addr stream byte) -> _/eax: byte
 #sig copy-bytes src: (addr byte), dest: (addr byte), n: int
 sig copy-array-object src: (addr array _), dest-ah: (addr handle array _)
 sig copy-file src: (addr buffered-file), dest-ah: (addr handle buffered-file), filename: (addr array byte)
+
+sig integer-divide a: int, b: int -> _/eax: int, _/edx: int
diff --git a/406int32.mu b/406int32.mu
index 4d762678..d69fe8e2 100644
--- a/406int32.mu
+++ b/406int32.mu
@@ -1,106 +1,5 @@
 # Some slow but convenient helpers
 
-# slow, iterative divide instruction
-# preconditions: _nr >= 0, _dr > 0
-fn try-divide _nr: int, _dr: int -> _/eax: int {
-  # x = next power-of-2 multiple of _dr after _nr
-  var x/ecx: int <- copy 1
-  {
-#?     print-int32-hex 0, x
-#?     print-string 0, "\n"
-    var tmp/edx: int <- copy _dr
-    tmp <- multiply x
-    compare tmp, _nr
-    break-if->
-    x <- shift-left 1
-    loop
-  }
-#?   print-string 0, "--\n"
-  # min, max = x/2, x
-  var max/ecx: int <- copy x
-  var min/edx: int <- copy max
-  min <- shift-right 1
-  # narrow down result between min and max
-  var i/eax: int <- copy min
-  {
-#?     print-int32-hex 0, i
-#?     print-string 0, "\n"
-    var foo/ebx: int <- copy _dr
-    foo <- multiply i
-    compare foo, _nr
-    break-if->
-    i <- increment
-    loop
-  }
-  var result/eax: int <- copy i
-  result <- decrement
-#?   print-string 0, "=> "
-#?   print-int32-hex 0, result
-#?   print-string 0, "\n"
-  return result
-}
-
-fn test-try-divide-1 {
-  var result/eax: int <- try-divide 0, 2
-  check-ints-equal result, 0, "F - try-divide-1"
-}
-
-fn test-try-divide-2 {
-  var result/eax: int <- try-divide 1, 2
-  check-ints-equal result, 0, "F - try-divide-2"
-}
-
-fn test-try-divide-3 {
-  var result/eax: int <- try-divide 2, 2
-  check-ints-equal result, 1, "F - try-divide-3"
-}
-
-fn test-try-divide-4 {
-  var result/eax: int <- try-divide 4, 2
-  check-ints-equal result, 2, "F - try-divide-4"
-}
-
-fn test-try-divide-5 {
-  var result/eax: int <- try-divide 6, 2
-  check-ints-equal result, 3, "F - try-divide-5"
-}
-
-fn test-try-divide-6 {
-  var result/eax: int <- try-divide 9, 3
-  check-ints-equal result, 3, "F - try-divide-6"
-}
-
-fn test-try-divide-7 {
-  var result/eax: int <- try-divide 0xc, 4
-  check-ints-equal result, 3, "F - try-divide-7"
-}
-
-fn test-try-divide-8 {
-  var result/eax: int <- try-divide 0x1b, 3  # 27/3
-  check-ints-equal result, 9, "F - try-divide-8"
-}
-
-fn test-try-divide-9 {
-  var result/eax: int <- try-divide 0x1c, 3  # 28/3
-  check-ints-equal result, 9, "F - try-divide-9"
-}
-
-# only positive dr for now
-fn try-modulo nr: int, dr: int -> _/eax: int {
-  var _positive-nr/eax: int <- abs nr
-  var positive-nr/ecx: int <- copy _positive-nr
-  var result/eax: int <- try-divide positive-nr, dr
-  result <- multiply dr
-  result <- subtract positive-nr
-  result <- negate
-  return result
-}
-
-fn test-try-modulo-negative-nr {
-  var result/eax: int <- try-modulo -0xa, 7
-  check-ints-equal result, 3, "F - test-try-modulo-negative-nr"
-}
-
 # slow, iterative shift-left instruction
 # preconditions: _nr >= 0, _dr > 0
 fn repeated-shift-left nr: int, dr: int -> _/eax: int {
diff --git a/apps/tile/value.mu b/apps/tile/value.mu
index c3ff5fe4..790b2de2 100644
--- a/apps/tile/value.mu
+++ b/apps/tile/value.mu
@@ -155,8 +155,10 @@ fn render-screen screen: (addr screen), row: int, col: int, _target-screen: (add
 }
 
 fn hash-color val: int -> _/eax: int {
-  var result/eax: int <- try-modulo val, 7  # assumes that 7 is always the background color
-  return result
+  var quotient/eax: int <- copy 0
+  var remainder/edx: int <- copy 0
+  quotient, remainder <- integer-divide val, 7  # assumes that 7 is always the background color
+  return remainder
 }
 
 fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), _row: int, _col: int {