Shifting Instructions

• SHIFT LEFT/RIGHT

Shifts each bit one position to the right or left.  For left shifts the "empty" bit position (D0, least significant bit, LSB) will be loaded with 0.  For right shifts the empty bit position (most siginifcant bit, MSB) will usually keep the value it had (sign extension) but there may be versions of the instruction that shift a 0 into the MSB.  For both directions, the bit that is shifted out is usually shifted into the Carry bit, which provides the linkage for multi-stage shifts.

• ROTATE LEFT/RIGHT

The same as shift, except that the bit that is shifted out is shifted back into the empty bit position.  It is also shifted into the Carry bit at the same time.

• SHIFT LEFT/RIGHT THROUGH CARRY BIT

The same as shift, except that the Carry bit is shifted into the empty bit position.

• ROTATE LEFT/RIGHT THROUGH CARRY BIT

The same as rotate, except that the Carry bit is included in the rotate, so the Carry bit value is rotated into the empty bit, and the bit shifted out is shifted into the Carry bit (but not into the empty bit position).

 

Program Flow Instructions: Unconditional Jumps

• JUMP

PC (program counter) = jump destination address.  Execution continues at this new address.

Program Flow Instructions: Conditional Branching

• BRANCH EQUAL / NOT EQUAL (TO ZERO)

• BRANCH CARRY / NO CARRY

• BRANCH POSITIVE / NEGATIVE

if the condition is true, PC = branch destination address, otherwise PC = next instruction address

Program Flow Instructions: Subroutine Calls and Returns

• CALL

Save return address

PC = call destination address

• RETURN

PC = saved return address

Subroutines are one of the most basic forms of code reuse. If you have a piece of code that needs to be run at different times and/or with different data, a subroutine lets you isolate that code and run it ("call it") from any other section of code, at any time. In fact, a subroutine can even call itself, but that's getting into recursion, which is not something we'll be discussing.

The essence of a subroutine call instruction is that it is a jump (jumping to the subroutine code), but a jump that remembers where it came from. By remembering the address that it came from, at the end of the subroutine it can jump back to where it came from so the calling code can continue. To be more precise, a subroutine call instruction is a jump instruction which saves the address of the instruction following the subroutine call instruction, not the address of the subroutine call instruction itself. It is the next instruction that needs to be executed after the subroutine returns. If the subroutine returned to the subroutine call instruction, the program would find itself in an endless loop, calling the subroutine without end.

The call instruction needs to have a known location to save the PC value so the subroutine can return. Normally this known location can be one of two places. The PC value can be saved in memory on a stack, which is pointed to by a CPU register, or it can be saved directly in a register (typically called the "link" register). The advantage of the stack is that subroutines can call other subroutines, and the stack will just continue to grow to hold all the return addresses. The advantage of the link register is that storing and retrieving data from registers is faster than storing and retrieving from memory. The disadvantage of the link register, if you want to call it that, is that if a subroutine wants to call another subroutine it needs to explicitly save the link register contents on a stack. A subroutine that calls other subroutines is often called a branch subroutine, which a subroutine that does not call any other subroutines is called a leaf subroutine. Calls to and returns from leaf subroutines can be faster with a link register, at the expense of requiring branch subroutines to manually save and restore the link register. In any case, either method performs the necessary function of saving the PC value in a known location so that it can be retrieved and loaded back into the PC at the end of the subroutine.

To return from a subroutine, as noted, the PC must be loaded with the address that was saved when the subroutine was called. And as mentioned, this address could be in memory on a stack, or it could be in alink register. Many CPUs have a special instruction called a "return" instruction that fetches the address and sticks it into the PC. Some CPUs just use a standard move instruction to move the saved address into the PC. But the result is the same in any case - the program continues to execute where it left off.