From 6f65b65f7d7261d79b58df25e5e0b20bfbc240ec Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 27 Nov 2020 13:24:50 -0800 Subject: [PATCH] 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. --- 314divide.subx | 17 ++++++++ 400.mu | 2 + 406int32.mu | 101 --------------------------------------------- apps/tile/value.mu | 6 ++- 4 files changed, 23 insertions(+), 103 deletions(-) create mode 100644 314divide.subx 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 {