Instructions
============

In general, instructions have the same names, flags,
and expect the same arguments as defined in the [spec].
This file lists all instructions that are modified
in some way, usually to improve usability.


Multiple arguments
------------------

The following instructions can accept more than one point argument:

```
ALIGNRP <point>+
FLIPPT  <point>+
IP      <point>+
SHP[a]  <point>+
```


Identifier arguments
--------------------

The following instructions can accept an identifier
instead of an index. Identifiers must be declared
in the `cvt` or `storage` [block](blocks.md).

```
MIAP[a]     <point> <cvtID|index>
MIRP[abcde] <point> <cvtID|index>

WCVTP <cvtID|index> <value>
WCVTF <cvtID|index> <value>
RCVT  <cvtID|index>

WS <storageID|index> <value>
RS <storageID|index>
```


Function definitions
--------------------

The `FDEF` instruction is more verbose than defined in the spec.
Its first argument is the function index, followed by the function identifier.
Then follows a list of parameter names, which are used to parse
the arguments of the corresponding `CALL` instructions.

Because functions may push values onto the stack, the compiler does not
consolidate push instruction across `CALL` instructions. However, if a
function consumes all its arguments and does not influence the stack for
subsequent instructions, it can be declared with the `void` instruction
instead of `FDEF`, to enable a more aggressive optimization.

```
FDEF <index> <funcID> <param>*
void <index> <funcID> <param>*
```

Parameters are typed, which allows the compiler to look up identifiers
and validate function calls. The type of a parameter is declared by
adding a prefix to its name. The name may be empty and only consist
of the prefix. The following prefixes are available:

```
val  = Numeric value
pt   = Point
cvt  = Control value identifier
func = Function identifier
stor = Storage identifier
```

Example:

```
void 9 interpolate pt ptRef1 ptRef2
  SRP2
  SRP1
  DUP
  IP
  MDAP[rnd]
ENDF
```


Function calls
--------------

When calling a function with the `CALL` instruction, the
function parameters can be listed after the function identifier:

```
CALL           <funcID> <param>*
LOOPCALL <int> <funcID> <param>*
```

Example:

```
CALL align 8         | PUSHB[001]
LOOPCALL 2 align 8 6 |  8 31
                     | CALL
                     | PUSHB[011]
                     |  8 6 2 31
                     | LOOPCALL
```


Push instruction
----------------

Instead of the various `*PUSH*` instructions, the custom
`push` instruction can be used, which accepts an arbitrary
list of values and is translated to appropriate pushes:

```
push 4 2 314 | PUSHB[001]
             |  4 2
             | PUSHW[000]
             |  314
```


Delta instructions
------------------

The `deltac` and `deltap` instructions are used
in place of the standard `DELTA*` instructions.
Their arguments consist of a control value identifier
or a point number, followed by a sequence of modifiers:

```
deltac <cvtID> <deltaModifier>+
deltap <point> <deltaModifier>+
```

Each modifier consists of a ppem value and a signed step value.
For example, `29-6` causes a shift of -6 steps at a ppem of 29.
The compiler generates appropriate `SDB` and `DELTA*` instructions:

```
deltap 8 11+2 29-6 | PUSHB[110]
                   |  34 8 1 9 8 1 11
                   | SDB
                   | DELTAP1
                   | DELTAP2
```


Unsupported instructions
------------------------

```
NPUSHB
NPUSHW
PUSHB[abc]
PUSHW[abc]  (See push)

IDEF          (Not yet implemented)
GETVARIATION  (Not yet implemented)

AA     (Deprecated)
SANGW  (Deprecated)
```


[spec]: https://docs.microsoft.com/typography/opentype/spec/tt_instructions
