Reworked registers.md
to hell and back.
Now also lists scratch registers.
This commit is contained in:
parent
b29622e238
commit
cabdda89b8
132
registers.md
132
registers.md
|
@ -1,82 +1,94 @@
|
|||
Registers in MAL
|
||||
================
|
||||
|
||||
Program registers
|
||||
The MAL-1 has 13 registers, 10 of them directly accessible, 2 of them virtual,
|
||||
and 1 completely obscured. In this article we'll cover them in detail. We'll
|
||||
look at which can be read from, written to, and which is safe to use for
|
||||
arithmetic purposes.
|
||||
|
||||
The Complete List
|
||||
-----------------
|
||||
|
||||
### PC
|
||||
The *Program Counter* holds the address of the next instruction byte.
|
||||
Below is a complete list of all registers and virtual registers in the MAL-1
|
||||
architecture:
|
||||
|
||||
### MBR
|
||||
The *Memory Buffer Register* stores the single byte that is read from the
|
||||
address specified in **PC**. This register is special as it can be read as two
|
||||
different registers:
|
||||
- `PC`: The **Program Counter**. It holds the address of the next instruction
|
||||
byte. Can be both read and written.
|
||||
|
||||
#### MBR
|
||||
When read as MBR, the register reads as a 32-bit signed integer. The 32-bit
|
||||
signed integer is sign extended from an 8-bit signed integer and thus has the
|
||||
range -128 to 127.
|
||||
- `MBR`: The **Memory Buffer Register**. It stores the byte read from the
|
||||
address in `PC`. Cannot be written to. Can be read as a signed byte (-128 to
|
||||
127), from the `MBR` address, or as an unsigned byte (0 to 255) from the
|
||||
`MBRU` address.
|
||||
|
||||
#### MBRU
|
||||
When read as *Memory Buffer Register Unsigned*, the register reads as a 32-bit
|
||||
*unsigned* integer. The 32-bit signed integer is extended with zeros from an
|
||||
8-bit *unsigned* integer and thus has the range 0 to 255.
|
||||
- `OPC`: The **Old Program Counter**. It should technically store the previous
|
||||
value of the `PC` register, but is frequently used as a *scratch register*.
|
||||
Can be both read and written.
|
||||
|
||||
### OPC
|
||||
The *Old Program Counter* is used to store the old value of the **PC**-register,
|
||||
although it is very commonly used as a *scratch register* for storing other
|
||||
values.
|
||||
- `MPC`: The **Micro-Program Counter**. It holds the address of the next micro
|
||||
program word. It is automatically set after very operation. Cannot be
|
||||
read or written directly, though the `goto` statement in MAL will allow one
|
||||
to set it.
|
||||
|
||||
### MPC
|
||||
The *Micro-Program Counter* point so the current position in the microcode. It
|
||||
is automatically set after very operation.
|
||||
- `MAR`: The **Memory Address Register**. Holds the address of the next `rd`
|
||||
or `wr` statement. Is used in conjunction with `MDR`. Cannot be read from,
|
||||
only written to.
|
||||
|
||||
Read and write
|
||||
--------------
|
||||
- `MDR`: The **Memory Data Register**. Holds the data that has either just
|
||||
been read from address `MAR` in memory, or is going to be written to address
|
||||
`MAR` in memory. Can be used as a *scratch register*. Can be both read and
|
||||
written.
|
||||
|
||||
### MAR
|
||||
The *Memory Address Register* contains the address of the 32-bit word that the
|
||||
next read or write is going to use. This register can only be written to, not
|
||||
read from.
|
||||
- `SP`: The **Stack Pointer**. Holds the address of the top-most element of
|
||||
the stack. Can be both read and written.
|
||||
|
||||
### MDR
|
||||
The *Memory Data Register* contains the data that has just been read in the case
|
||||
of a *read* operation or is to be written in the case of a *wr* operation.
|
||||
- `LV`: The **Local Variables pointer**. Points to the lowest of the local
|
||||
variables in the current *stack frame*, that is the lowest of the local
|
||||
variables for the currently executing function. Can be both read and
|
||||
written.
|
||||
|
||||
### MBR
|
||||
See **MBR** under *Program registers*
|
||||
- `CPP`: The **Contant Pool Pointer**. Points to the lowest element of the
|
||||
constant pool. Can be both read and written.
|
||||
|
||||
Stack registers
|
||||
---------------
|
||||
- `TOS`: The **Top Of Stack**. Contains the *value* of the uppermost stack
|
||||
element. It is not a pointer. Can be used as a *scratch register*, but
|
||||
should always be set back at the end of the instruction. Can be both read
|
||||
and written.
|
||||
|
||||
### SP
|
||||
The *Stack Pointer* register contains a pointer to the top-most element of the
|
||||
stack.
|
||||
- `H`: The **Hold register**. Contains any value the developer wishes. Is
|
||||
required for many arithmetic operations. (See
|
||||
[Operations](./operations.md).) Can be both read and written.
|
||||
|
||||
### LV
|
||||
The *Local Variables* register points to the lowest of the local variables in
|
||||
the current *stack frame*, that is the lowest of the local variables for the
|
||||
currently executing function.
|
||||
- `Z` & `N`: The **Zero** and **Negative** registers are *virtual registers*.
|
||||
At the end of an ALU operation `Z` is automatically set to *on* if the
|
||||
output is `0`. Likewise `N` is set to *on* if the output is `< 0`. Cannot be
|
||||
read or written directly. Can only be used as arguments to the `if`
|
||||
statement. (See [Operations](./operations.md))
|
||||
|
||||
### CPP
|
||||
The *Constant Pool Pointer* points to the lowest element of the constant pool.
|
||||
Scratch Registers
|
||||
-----------------
|
||||
|
||||
### TOS
|
||||
The *Top Of Stack* register contains the *value* of the uppermost element on the
|
||||
stack--it is *not* a pointer. This is, however, not a requirement that the
|
||||
developer is bound to follow when coding own instructions. The register should
|
||||
however always be set to the value of the top element at the end of the
|
||||
instruction.
|
||||
To achieve the best possible performance, it is often wise to avoid any
|
||||
interaction with memory while doing arithmetic work. This can be accomplished by
|
||||
exclusively using registers for most work. Unfortunately most MAL registers are
|
||||
unsuited for this.
|
||||
|
||||
Arithmetics
|
||||
-----------
|
||||
For a register to be suitable as a *scratch register*, it needs to achieve
|
||||
following requirements:
|
||||
|
||||
### H
|
||||
The *Hold* register is used to hold the left operand in the operations performed
|
||||
by the ALU.
|
||||
1. The register can be both read from and written to.
|
||||
2. The register's primary function is either:
|
||||
- Rarely used (eg `OPC`)
|
||||
- Deliberately as as a *scratch register* (eg `H`)
|
||||
- To contain a value easily retrieved from elsewhere (`TOS`)
|
||||
|
||||
### Z & N
|
||||
The *Zero* and *Negative* registers are *virtual registers*. They are
|
||||
automatically set after any ALU operation. A MAL `if(x)` statement can only
|
||||
accept *Z* and *N* as input. *Z* is on if the output of the latest ALU operation
|
||||
was zero. *N* is on if the output was negative.
|
||||
Below is a list of registers on the MAL-1 suitable as *scratch registers*, why
|
||||
they are usable in this fashion, and possible quirks:
|
||||
|
||||
- `OPC`: Rarely used.
|
||||
- `MDR`: Can store any value when not being used for writing or reading
|
||||
memory. It can even be useful to use it as the "final" result register, for
|
||||
stack operations like `add` or `sub`.
|
||||
- `TOS`: Should always contain the same value as the top element of the stack
|
||||
in memory at the end of an operation, but can be used in any other way
|
||||
before then. It is also a useful "final" result register similar to `MDR`.
|
||||
- `H`: Is defined as a *scratch register*, and can be used in any way.
|
||||
|
|
Loading…
Reference in New Issue
Block a user