From 189bd674a05316f0164d3eca86a048e24b662b99 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 26 Oct 2021 21:54:01 -0700 Subject: [PATCH] a few surprisingly nuanced tweaks to task 8 Thanks sejo for the feedback. --- mu.md | 32 +++++++++++++++++--------------- tutorial/index.md | 14 +++++++------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/mu.md b/mu.md index ff697d32..7cd5959c 100644 --- a/mu.md +++ b/mu.md @@ -101,17 +101,20 @@ Other miscellaneous restrictions: by being written to a memory location. When you need that sort of thing, use a `handle` instead. -## Primitive statement types +## Operations on simple types -These usually operate on variables with 32-bit types, with some restrictions -noted below. Most instructions with multiple args require types to match. - -Some notation for describing statement forms: - - `var/reg` indicates a variable in some register. Sometimes we require a - variable in a specific register, e.g. `var/eax`. - - `var/xreg` indicates a variable in some floating-point register. - - `var` without a `reg` indicates either a variable on the stack or +We'll now survey a long list of statement forms that operate on 32-bit types. +Most of these are primitives, but some are also implemented as functions +(which have slightly different rules as mentioned up top). Most instructions +with multiple args require types to match. Various operations have other +restrictions which we'll note below, using the following notation: + - `var/reg` indicates a variable in some register. Where we require a + variable in a specific register, we'll mention it explicitly. E.g. + `var/eax`. + - `var/xreg` indicates a variable in some floating-point register `xmm_`. + - `var` without a `reg` indicates either a variable on the stack, or dereferencing a variable in a (non-floating-point) register: `*var/reg`. + - `var: type` indicates a variable that must satisfy some type constraint. - `n` indicates a literal integer. There are no floating-point literals. ### Moving values around @@ -154,7 +157,8 @@ there's a few ways to convert non-float values in general-purpose registers. var/xreg <- convert *var2/reg2 ``` -Correspondingly, there are ways to convert floats into integers. +Correspondingly, there are ways to convert floats into integers, with and +without rounding. ``` var/reg <- convert var2/xreg2 @@ -170,15 +174,13 @@ Still, the absence of fractional literals is an annoyance. Mu provides some helpers to mitigate it somewhat: ``` - result/xmm0 <- rational nr: int, dr: int - fill-in-rational out: (addr float), nr: int, dr: int + result/xmm0 <- rational numerator: int, denominator: int + fill-in-rational out: (addr float), numerator: int, denominator: int ``` These are functions, so the inouts have fewer restrictions while the outputs have more. The inouts can be registers, or memory, or even literals. The -output for `rational` _must_ be in register `xmm0`. The `:` notation describes -type constraints; `nr` and `dr` are required to be integers, while `out` must -be an address to a float. +output for `rational` _must_ be in register `xmm0`. ### Comparing values diff --git a/tutorial/index.md b/tutorial/index.md index 68dd29aa..cea31945 100644 --- a/tutorial/index.md +++ b/tutorial/index.md @@ -287,20 +287,20 @@ Run `translate` (or `translate_emulated`) as usual. Use your runbook from Task All our variables so far have had type `int` (integer), but there are limits to what you can do with just whole integers. For example, here's the formula -a visitor to the US will require to convert a distance on a road sign to -kilometers: +a visitor to the US will require to convert distances mentioned on road signs +from miles to kilometers: ``` distance * 1.609 ``` Write a function to perform this conversion. Some starting points: -- reread [the section on variables and registers](https://github.com/akkartik/mu/blob/main/mu.md#variables-registers-and-memory) +* Reread [the section on variables and registers](https://github.com/akkartik/mu/blob/main/mu.md#variables-registers-and-memory) with special attention to the `float` type. -- read [the section on floating-point arithmetic](https://github.com/akkartik/mu/blob/main/mu.md#floating-point-arithmetic). -- One wrinkle is that the x86 instruction set doesn't permit literal - fractional arguments. So you'll need to _create_ 1.609 somehow. Relevant is - [the section on moving values around](https://github.com/akkartik/mu/blob/main/mu.md#moving-values-around). +* Read [the section on floating-point arithmetic](https://github.com/akkartik/mu/blob/main/mu.md#floating-point-arithmetic). +* One wrinkle is that the x86 instruction set doesn't permit literal + fractional arguments. So you'll need to _create_ 1.609 somehow. See the + sub-section on moving values around under [operations on simple types](https://github.com/akkartik/mu/blob/main/mu.md#operations-on-simple-types). This task has four source files in the repo that reveal more and more of the answer. Start from the first, and bump down if you need a hint.