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.
This commit is contained in:
parent
704265bd3c
commit
6f65b65f7d
|
@ -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
|
2
400.mu
2
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-bytes src: (addr byte), dest: (addr byte), n: int
|
||||||
sig copy-array-object src: (addr array _), dest-ah: (addr handle array _)
|
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 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
|
||||||
|
|
101
406int32.mu
101
406int32.mu
|
@ -1,106 +1,5 @@
|
||||||
# Some slow but convenient helpers
|
# 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
|
# slow, iterative shift-left instruction
|
||||||
# preconditions: _nr >= 0, _dr > 0
|
# preconditions: _nr >= 0, _dr > 0
|
||||||
fn repeated-shift-left nr: int, dr: int -> _/eax: int {
|
fn repeated-shift-left nr: int, dr: int -> _/eax: int {
|
||||||
|
|
|
@ -155,8 +155,10 @@ fn render-screen screen: (addr screen), row: int, col: int, _target-screen: (add
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash-color val: int -> _/eax: int {
|
fn hash-color val: int -> _/eax: int {
|
||||||
var result/eax: int <- try-modulo val, 7 # assumes that 7 is always the background color
|
var quotient/eax: int <- copy 0
|
||||||
return result
|
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 {
|
fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), _row: int, _col: int {
|
||||||
|
|
Loading…
Reference in New Issue