task: juggling function outputs between registers
This commit is contained in:
parent
0ccfd0156f
commit
a3f73278b1
|
@ -368,12 +368,12 @@ fn dither-pgm-unordered-monochrome _src: (addr image), _dest: (addr image) {
|
||||||
curr-int <- shift-left 0x10 # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow
|
curr-int <- shift-left 0x10 # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow
|
||||||
var error/esi: int <- _read-dithering-error errors, x, y, src-width
|
var error/esi: int <- _read-dithering-error errors, x, y, src-width
|
||||||
error <- add curr-int
|
error <- add curr-int
|
||||||
$_dither-pgm-unordered-monochrome:update-error: {
|
$dither-pgm-unordered-monochrome:update-error: {
|
||||||
compare error, 0x800000
|
compare error, 0x800000
|
||||||
{
|
{
|
||||||
break-if->=
|
break-if->=
|
||||||
_write-raw-buffer dest-data, x, y, src-width, 0/black
|
_write-raw-buffer dest-data, x, y, src-width, 0/black
|
||||||
break $_dither-pgm-unordered-monochrome:update-error
|
break $dither-pgm-unordered-monochrome:update-error
|
||||||
}
|
}
|
||||||
_write-raw-buffer dest-data, x, y, src-width, 1/white
|
_write-raw-buffer dest-data, x, y, src-width, 1/white
|
||||||
error <- subtract 0xff0000
|
error <- subtract 0xff0000
|
||||||
|
|
|
@ -354,6 +354,48 @@ the precise register a function header specifies. The return value can even be
|
||||||
a literal integer or in memory somewhere. The `return` is really just a `copy`
|
a literal integer or in memory somewhere. The `return` is really just a `copy`
|
||||||
to the appropriate register(s). This is why the second example above is legal.
|
to the appropriate register(s). This is why the second example above is legal.
|
||||||
|
|
||||||
|
## Task 9: juggling registers between function calls
|
||||||
|
|
||||||
|
Here's a program:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn f -> _/eax: int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g -> _/eax: int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add-f-and-g -> _/eax: int {
|
||||||
|
var x/eax: int <- f
|
||||||
|
var y/eax: int <- g
|
||||||
|
x <- add y
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
What's wrong with this program? How can you fix it and pass all tests by
|
||||||
|
modifying just function `add-f-and-g`?
|
||||||
|
|
||||||
|
By convention, most functions in Mu return their results in register `eax`.
|
||||||
|
That creates a fair bit of contention for this register, and we often end up
|
||||||
|
having to move the output of a function call around to some other location to
|
||||||
|
free up space for the next function we need to call.
|
||||||
|
|
||||||
|
An alternative approach would be to distribute the load between registers so
|
||||||
|
that different functions use different output registers. That would reduce the
|
||||||
|
odds of conflict, but not eradicate them entirely. It would also add some
|
||||||
|
difficulty in calling functions; now you have to remember what register they
|
||||||
|
write their outputs to. It's unclear if the benefits of this alternative
|
||||||
|
outweigh the costs, so Mu follows long-established conventions in other
|
||||||
|
Assembly languages. I do, however, violate the `eax` convention in some cases
|
||||||
|
where a helper function is only narrowly useful in a single sort of
|
||||||
|
circumstance and registers are at a premium. See, for example, the definition
|
||||||
|
of the helper `_read-dithering-error` [when rendering images](http://akkartik.github.io/mu/html/511image.mu.html).
|
||||||
|
The leading underscore indicates that it's an internal detail of
|
||||||
|
`render-image`, and not really intended to be called by itself.
|
||||||
|
|
||||||
## Task 10: operating with fractional numbers
|
## Task 10: operating with fractional numbers
|
||||||
|
|
||||||
All our variables so far have had type `int` (integer), but there are limits
|
All our variables so far have had type `int` (integer), but there are limits
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
fn f -> _/eax: int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g -> _/eax: int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add-f-and-g -> _/eax: int {
|
||||||
|
var _x/eax: int <- f
|
||||||
|
var x/ecx: int <- copy _x
|
||||||
|
var y/eax: int <- g
|
||||||
|
x <- add y
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test-add-f-and-g {
|
||||||
|
var result/eax: int <- add-f-and-g
|
||||||
|
check-ints-equal result, 5, "F - test-add-f-and-g\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main {
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
fn f -> _/eax: int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g -> _/eax: int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add-f-and-g -> _/eax: int {
|
||||||
|
var x/eax: int <- f
|
||||||
|
var y/eax: int <- g
|
||||||
|
x <- add y
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test-add-f-and-g {
|
||||||
|
var result/eax: int <- add-f-and-g
|
||||||
|
check-ints-equal result, 5, "F - test-add-f-and-g\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main {
|
||||||
|
}
|
Loading…
Reference in New Issue