7.1. Types of Instruction Sets
Most of the information in this chapter is contained in the document 8-bit AVR Instruction Set or its equivalent HTML version.
The decision about what instructions will be possible to execute in a microprocessors is one of the most important and has a profound effect in the performance when executing programs. Furthermore, the set of instructions and the processor architecture are tightly coupled. For example, the operands for most of the instructions are stored in the register file, thus, it must allow for these operands to be accessed efficiently. The AVR architecture, for example, allows various combinations when accessing the operands in the stage Register Operand Fetch.
The other criteria that influences the type of instructions supported by a microprocessor is the complexity of the implementation. Ultimately, the instructions need to be sequenced by a digital circuit. The higher the complexity of the tasks carried out by an instruction, the higher the complexity of the design. This complexity usually translates into a large number of gates that require a larger physical space (larger chip) and more power consumption.
Consider the following example. Should a processor include as part of its machine language an instruction that given a real number and the coefficients of a second order polynomial obtains its corresponding value? Suppose we call this instruction SDPE
(second degree polynomial evaluation). One possible format of this instruction could be:
SDPE a, b, c, n, dest
The instruction would evaluate the polynomial using the three coefficients and the additional value, and store the result in location dest
. The evaluation would calculate the value with the formula:
Although such instruction could be useful, a processor without such instruction could still calculate the same result executing a sequence of instructions to perform the required additions and multiplications. Thus the trade-off to explore when designing a microprocessor is between the complexity of the architecture, and the performance obtained by including certain operations in the ISA. A microprocessor with a reduced set of instructions may require more operations to perform sophisticated calculations, but they are executed faster due to its simplicity. Conversely, a microprocessor with a large number of instructions may require much shorter instruction sequences, but they may take longer to execute due to their complexity.
Over the years microprocessor manufacturers have explored this trade-off and created two categories of systems depending on the complexity of the machine languages.
7.1.1. Complex Instruction Set Computers (CISC)
The processors that provide a rich and complex set of instructions are called Complex Instruction Set Computers or CISC. These instructions typically use several operands and may require multiple memory accesses. There are various examples of CISC microprocessors, but perhaps the most popular architectures of this type are Intel’s x86, IA-32, and IA-64 (also known as Itanium, x86_64 or AMD64.) The x86 architecture was present in the personal computers in 1970s. The architecture was then evolved to the IA-32 (32 bit bus), and then the 64 bit version. These processors are present in numerous desktop computers, servers, and laptops. Other examples of CISC architectures are those in systems such as IBM’s System/360, DEC PDP-11, DEC VAX, or Motorola 68k.
The machine instructions in a CISC computer allow handling multiple operands, some or all of them in memory, and accessed with address manipulations that may require certain arithmetic operations. For example, the following instruction is part of the IA-32 architecture:
ADD $4, 14(%eax, %ebx, 8)
and adds the value 4 to the data in memory stored in the address obtained by adding the value 14, the content of register %eax
, and the content of register %ebx
multiplied by 8. As you can see, the execution of this instruction requires more than one arithmetic operation. The addition denoted by the instruction code (ADD
) can be performed once the operands are obtained, and additional additions, and even a multiplication is needed to obtain the second operand.
7.1.2. Reduced Instruction Set Computers (RISC)
RISC architectures appeared as an alternative to existing CISC microprocessors. The philosophy is the opposite, microprocessors have a very reduce set of instructions performing each a very simple operation. The idea is to translate this simplicity in the functionality into a faster execution, and a simpler structure in the microprocessor. A reduced execution time does not necessarily translate into a processor that is faster than a CISC architecture. A simple set of instructions means that complex operations will require sequences of instructions, some of them very large.
Some examples of current RISC architectures are:
- MIPS (Microprocessor without Interlocked Pipeline Stages): used in some routers, Nintendo consoles, original PlayStation, PlayStation 2 and PSP.
- ARM: present in numerous computers and personal devices such as digital cameras, mobile phones, iPod, etc.
- SPARC (Scalable Processor ARChitecture): powered the systems sold by Sun Microsystems (now owned by Oracle).
- PowerPC (Performance OPtimization with Enhanced RISC - Performance Computing): It was created by a consortium of Apple, IBM and Motorola in the early 1990s to be used in personal computers. Not widely used these days.
- AVR architecture. This architecture is now included in multiple microcontrollers used in embedded systems. Some of the systems in the Arduino family use microprocessors with this architecture.
The comparison between RISC and CISC architectures cannot be done solely in terms of the number of instructions executed per unit of time. With that measure, RISC processors are clear winners. A more exact comparison is to execute the same high level task in two processors and measure the amount of time it takes to finish the task, instead of the number of instructions executed. Very likely, the CISC architecture will execute a smaller number of instructions, but each of them will take longer than the RISC architecture.
7.1.3. Fixed vs Variable Size Instruction Encoding
Another important feature of a microprocessor that can be used to divide them into two categories is the format in which the instructions are encoded. In processors that use a fixed length format, every instruction has exactly the same size. This feature has numerous consequences in the design stage. Typically, a small number of operands are allowed in every instruction. A large number of operands would make the format longer, and perhaps not fully used by all the instructions. The number of different instructions is also reduced as a larger number of instructions translates into a larger number of possible cases to encode, and eventually into a larger format. The main advantage of these instructions is in the decoding stage. That is, when the instruction has been loaded in the instruction register, the processor needs to identify which one it is and the type of operands that are required. A fixed format greatly simplifies this stage as the bits encoding the different elements of the instruction are located in the same positions.
The processors with a variable length format, on the other hand, allow instructions to be encoded with different number of bits. Thus, an instruction may have an arbitrary number of operands as they will be encoded with additional bits. The main disadvantage of this approach is during the decoding stage, that is, when the processor needs to identify the type of instruction to execute and obtain all its operands. In these processors, the decoding stage may require loading additional bytes from memory while the instruction is being decoded.
The following video summarizes the differences between CISC and RISC architecture..
7.2. Instruction Format of AVR Architecture
The AVR architecture has a fixed length format. All instructions (with only a few exceptions) are encoded with 16 bits. When describing the different components of an instruction, we will be using the following convention for registers and operands:
Rd
: A register in the register file that will be the destination of the result derived from the instruction.Rr
: A register in the register file which will provide one of the operands for the instruction.R
: Result of the instruction after its execution.K
: A constant value.k
: A constant memory address.b
: A bit in a register in the register file or an input/output register.s
: One of the bits of the status register.X
,Y
,Z
: 16 bit registers obtained combining two registers in the register file (X=R27:R26
,Y=R29:R28
,Z=R31:R30
).
The following figure shows some of the instruction encoding schemes used by the AVR architecture.
Some of the Instruction Encoding Schemes in the AVR Architecture
Every instruction must have some bits to encode the type of operations that is required. These bits are called the operation code. The AVR architecture uses a variable number of bits to encode the operation. In its minimum version, the left-most four bits are used.
Instructions for which the operands are one of the 32 general purpose registers, require five bits per operand (
ADD R0, R31
is encoded as shown in the following figure:
Encoding of the ADD
instruction
The instruction implements the operation
ADD
operation would be denoted by
ADD Rd, Rr
. Note that the first operand is both a source operand and the destination in which the result is going to be stored. As a consequence, the content of
R0
before the execution of the instruction is lost. The top part of the previous figure shows the encoding of these instructions for any register number, whereas the bottom part shows the exact encoding for that instruction. As you can see, the five bits in the format with the letter
r (source operand) have value
11111 referring to register
R31
. Analogously, the five bits denoted by
d (destination operand) have value
00000 referring to register
R0
. The hexadecimal representation of this instruction is
0x0E0F
.
Some instructions allow a number as operand instead of a register. These numbers that appear literally in instructions are called immediate operands. The reason for this name will become apparent when the addressing modes are described. These operands require the number to be encoded with bits that are part of the instruction format. For example, the instruction
CPI R16, 255
is encoded as shown in the following figure:
Encoding of the CPI
instruction
This type of instruction is generically represented by CPI Rd, K
. This encoding shows some consequences of trying to maintain the format of the instructions of the same size. The operation code are the four left-most bits with value 0011
, they encode the CPI
part of the instruction. CPI
stands for compare with immediate and the instruction is going to compare the immediate operand (the number 255) with the content of register R16
. Internally, the microprocessor will carry out the operation R16 - 255
and update the status register to reflect the conditions of the result. In other words, instead of storing the value of the operation, only certain conditions are captured in the status register. The hexadecimal representation of this instruction is 0x3F0F
Since the instruction is encoded with 16 bits, and four of them are used for the operation code, this means that there are only 12 bits remaining to encode one register and a number. In principle, if we allow any of the 32 general purpose registers to be specified, there would be only 7 bits remaining to encode the immediate operand, leaving only the range of possible values
CPI
can only use 16 of the 32 general purpose registers. More precisely, this instruction can specify as first operand a register with index
As a consequence, the instruction CPI R7, 255
would be ruled incorrect because it does not correspond to the encoding in the AVR instruction format.
The third type of operands allowed in some instructions are values that must be used as memory addresses (not as simple numeric values). As in the case of the immediate operands, these values need to be encoded using the bits of the instruction which poses a challenge for the fixed format. For example, the instruction
LDS R12, 12565
loads the content of memory in position 12565
into register R12
. Its binary encoding must include the operation code, the register R12
and the memory address 12565
. Memory addresses in the AVR architecture have 16 bits. How is it possible to encode such instruction while remaining within the fixed format of 16 bits per instructions? There is no other solution than create an exception in the encoding. The LDS
instruction is one of the cases in the AVR architecture that uses 32 bits as shown in the following figure:
Encoding of the LDS
instruction
The operation code in this case is represented by 11 bits, the leftmost seven bits, plus the right most four of the first 16 bits. The second 16 bits encode the memory address. These instructions are generically described as LDS Rd, k
. The hexadecimal representation of this instruction is 0x91C03115
.
The set of steps taken by the microprocessor to execute this instruction are different from the previous ones. In this case, after obtaining the first 16 bits (hexadecimal 0x91C0
), the decoding stage detects that is a LDS
instruction and therefore a second memory word needs to be loaded with the address operand. This double access to memory, to fetch the instruction and to obtain the additional operand, will delay its execution time.
The following video shows some examples of how instructions are encoded in the AVR architecture..
7.3. The Assembly Language
To execute the instructions allowed by the architecture, all of them must be encoded with zeros and ones. The description of how to perform this encoding for each instruction is described in the document 8-bit AVR Instruction Set. But writing programs using this language and its binary encoding is extremely inconvenient.
The solution for this problem is to define a language with the same instructions, operands and formats as the machine language but instead of using binary logic, use combinations of letters and numbers so that it is understood by a programmer. This language is called assembly language and is the notation shown in the previous sections when describing the instructions.
Thus, the assembly language can be defined as a direct alphanumeric representation of the instructions executed by a microprocessor as part of its machine language. The translation between assembly language and a machine instruction is a straightforward application of simple encoding rules to transform each operand into a set of bits of the instruction format.
Consider again the assembly language instruction encoded as